If the expiration of the token is less than 3580 seconds, I want to update my access token with my refresh request before the new request I will send. And then I want to throw out my new request.

But when the refresh function calls, I enter the loop and get a 401 error. Then my onError method works and I am redirected to the login screen. How do I get out of this cycle? And how can I renew my token by checking my disappearance period before each request I will send?

My TokenExpireHelper class returns my expiration time by encoding the token from the shared value.

class AuthInterceptor extends QueuedInterceptorsWrapper {
  final Dio _dio;
  late final IUserServices _loginManager = UserServices();

  bool _isRefreshing = false;

  AuthInterceptor(this._dio);

  @override
  Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    if (options.headers["requiresToken"] == false) {
      // if the request doesn't need token, then just continue to the next interceptor
      options.headers.remove("requiresToken"); //remove the auxiliary header
      return handler.next(options);
    }

    bool accessTokenHasExpired = TokenExpireHelper().getExpireTime() < 3580 ? true : false;
    if (accessTokenHasExpired) {
      if (!_isRefreshing) {
        _isRefreshing = true;
        _loginManager.refreshToken().whenComplete(() => _isRefreshing = false);
        // Update the request header with the new access token
        if (access_token.$ != "") {
          options.headers['Authorization'] = 'Bearer ${access_token.$}';
          // Repeat the request with the updated header
          return handler.next(options);
        }
      }
    }

    print('REQUEST[${options.method}] => PATH: ${options.path}');
    return super.onRequest(options, handler);
  }

  @override
  Future<void> onError(DioException e, ErrorInterceptorHandler handler) async {
    if (e.response?.statusCode == 403 || e.response?.statusCode == 401) {
      // for some reasons the token can be invalidated before it is expired by the backend.
      // then we should navigate the user back to login page

      OneContext.instance.key.currentState!.pushNamedAndRemoveUntil("/signInView", (Route<dynamic> route) => false);
    }

    print(e.response?.statusCode);
    return handler.next(e);
  }

------- refresh function ( this function inside UserService class )

 @override
  Future<bool> refreshToken() async {
    final response = await _reqresManager.post(
      _RezyonRequestPaths.refresh.name,
      options: Options(headers: {
        "Content-Type": "application/json",
        "Authorization": "Bearer ${access_token.$}",
      }),
    );

    if (response.statusCode == HttpStatus.ok) {
      final String accessToken = response.data["access_token"];
      final int expireDate = response.data["expires_in"];

      print(accessToken);
      await access_token.load();
      access_token.$ = accessToken;
      await access_token.save();

      await expires_in.load();
      expires_in.$ = expireDate;
      await expires_in.save();
      print("refresh token works");
      return response.statusCode == HttpStatus.ok;
    }

    return false;
  }


0

There are 0 best solutions below