Home > other >  how to redirect the user to the login page if the token has expired
how to redirect the user to the login page if the token has expired

Time:12-29

hello I have a case where when the user token expires the user does not switch to the loginPage page, even though I have set it here. how do i solve this problem thanks.

enter image description here

i set it on splashscreen if token is not null then go to main page and if token is null then go to login page. but when the token expires it still remains on the main page

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

and function when user login

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;
                                        Navigator.pushNamedAndRemoveUntil(
                                          context,
                                          '/main',
                                          (route) => false,
                                        );
                                      }
                                    }
                                  },
                                ),

and this call api

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'];
        //Ini mulai nyimpen token
        await UtilSharedPreferences.setToken(token);
        print(token);
        // print(await UtilSharedPreferences.getToken());
        return User.fromJson(jsonDecode(response.body));
      } else {
        return null;
      }
    } catch (e) {
      print(e);
      throw Exception();
    }
  }

CodePudding user response:

If your session expire feature has some predefine interval or logic than you have to implement it in splash screen and based on that you can navigate user further. Otherwise you want to handle it in API response only you have add condition for statusCode 401.

if (response.statusCode == 200) { 
   //SuccessWork
} else if (response.statusCode == 401) {
   //SessionExpire
} else {
   return null
}

CodePudding user response:

you can just make your own HTTP client using Dio and add Interceptor to automatically regenerate idToken if expired using the refreshToken given.

Http client gives an error if the refreshToken also gets expired.

In that case, just navigate to the login screen.

Full code for adding interceptor and making own HTTP client is given below

import 'package:dio/dio.dart';

import '../utils/shared_preference.dart';

class Api {
  static Dio? _client;
  static Dio clientInstance() {
    if (_client == null) {
      _client = Dio();
      _client!.interceptors
          .add(InterceptorsWrapper(onRequest: (options, handler) async {
        if (!options.path.contains('http')) {
          options.path = 'your-server'   options.path;
        }
        options.headers['Authorization'] =
            'Bearer ${PreferenceUtils.getString('IdToken')}';
        return handler.next(options);
      }, one rror: (DioError error, handler) async {
        if ((error.response?.statusCode == 401 &&
            error.response?.data['message'] == "Invalid JWT")) {
          if (PreferenceUtils.exists('refreshToken')) {
            await _refreshToken();
            return handler.resolve(await _retry(error.requestOptions));
          }
        }
        return handler.next(error);
      }));
    }
    return _client!;
  }

  static Future<void> _refreshToken() async {
    final refreshToken = PreferenceUtils.getString('refreshToken');
    final response = await _client!
        .post('/auth/refresh', data: {'refreshToken': refreshToken});

    if (response.statusCode == 201) {
      // successfully got the new access token
      PreferenceUtils.setString('accessToken', response.data);
    } else {
      // refresh token is wrong so log out user.
      PreferenceUtils.deleteAll();
    }
  }

  static Future<Response<dynamic>> _retry(RequestOptions requestOptions) async {
    final options = Options(
      method: requestOptions.method,
      headers: requestOptions.headers,
    );
    return _client!.request<dynamic>(requestOptions.path,
        data: requestOptions.data,
        queryParameters: requestOptions.queryParameters,
        options: options);
  }
}

Dio client = Api.clientInstance();
var resposne = (hit any request);
   if(error in response is 401){
  //it is sure that 401 is because of expired refresh token as we 
  //already handled idTokoen expiry case in 401 error while 
  //adding interceptor.
navigate to login screen for logging in again.
}

Please accept the solution if it solves your problem.

  • Related