skip to Main Content

I have a problem where when the user’s token expires it should return to the login page, but the case I experienced was that it didn’t return to the login page, instead it gave an exception in the form of text ‘Token Expired’ in the widget.

is there something wrong with my code.

enter image description here

enter image description here

this is the code in the login page widget

 Container(
                      width: double.infinity,
                      height: 45,
                      child: isLoading
                          ? Center(
                              child: CircularProgressIndicator(
                                color: primaryColor,
                              ),
                            )
                          : CustomButtonFilled(
                              title: 'Login',
                              onPressed: () async {
                                final prefs =
                                    await SharedPreferences.getInstance();
                                prefs.setString(Constant.token, '');
                                if (nimController.text.isEmpty ||
                                    passwordController.text.isEmpty) {
                                  showError('NIM/Password harus diisi');
                                } else {
                                  setState(() {
                                    isLoading = true;
                                  });
                                  User? user = await userProvider.login(
                                    nimController.text,
                                    passwordController.text,
                                  );
                                  setState(() {
                                    isLoading = false;
                                  });
                                  if (user == null) {
                                    showError('NIM/Password tidak sesuai!');
                                  } else {
                                    userProvider.user = user;
                                    // ignore: use_build_context_synchronously
                                    Navigator.pushNamedAndRemoveUntil(
                                      context,
                                      '/main',
                                      (route) => false,
                                    );
                                  }
                                }
                              },
                            ),
                    ),

call API login

 Future<User?> login(String nim, String password) async {
    String url = Constant.baseURL;        try {
      var body = {
        'username': nim,
        'password': password,
      };
      var response = await http.post(
        Uri.parse(
          '$url/login_mhs',
        ),
        body: body,
      );
      if (response.statusCode == 200) {
        final token = jsonDecode(response.body)['data']['access_token'];
        await UtilSharedPreferences.setToken(token);
        print(token);
        return User.fromJson(jsonDecode(response.body));
      } else {
        return null;
      }
    } catch (e) {
      print(e);
      throw Exception();
    }
  }

widget splashscreen

Future<void> toLogin() async {
    Timer(
      const Duration(seconds: 3),
      () async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        String? token = prefs.getString(Constant.token);
        // ignore: use_build_context_synchronously
        Navigator.pushReplacementNamed(
          context,
          token != null ? AppRoute.mainRoute : AppRoute.loginRoute,
          arguments: token,
        );
      },
    );
  }

  @override
  void initState() {
    super.initState();
    toLogin();
  }

2

Answers


  1. To fix this issue, you can modify the toLogin() function to check if the token is empty and navigate to the login page in that case:

    Future<void> toLogin() async {
      WidgetsBinding.instance?.addPostFrameCallback(
        (_) {
          SharedPreferences prefs = await SharedPreferences.getInstance();
          String? token = prefs.getString(Constant.token);
    
          if (token == null || token.isEmpty) {
            Navigator.pushReplacementNamed(context, AppRoute.loginRoute);
          } else {
            Navigator.pushReplacementNamed(context, AppRoute.mainRoute);
          } 
        },
      );
    }
    
    Login or Signup to reply.
  2. You are saving the token as a String inside the shared preferences. That string will always be there and never expire. So when you do

    Navigator.pushReplacementNamed(
              context,
              token != null ? AppRoute.mainRoute : AppRoute.loginRoute,
              arguments: token,
            );
    

    It will never go to login page because the token is never null or empty. When you do post request to API, that is when it tells you the result where the token is expired, so you want to handle the page change after getting the results from the post request. So your code should be more like that:

    if (response.statusCode == 200) {
        return UserBiodata.fromJson(jsonDecode(response.body));
      } else {
        throw Exception('Token Expired');
        Navigator.pushReplacementNamed( context, AppRoute.loginRoute,);
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search