|
class AuthorizationInterceptor extends QueuedInterceptorsWrapper { |
|
final TokenRepository _tokenRepository; |
|
final AuthorizationRepository _authorizationRepository; |
|
final RefreshTokenRepository _refreshTokenRepository; |
|
|
|
AuthorizationInterceptor({ |
|
required TokenRepository tokenRepository, |
|
required AuthorizationRepository authorizationRepository, |
|
required RefreshTokenRepository refreshTokenRepository, |
|
}) : _tokenRepository = tokenRepository, |
|
_authorizationRepository = authorizationRepository, |
|
_refreshTokenRepository = refreshTokenRepository; |
|
|
|
@override |
|
void onRequest( |
|
RequestOptions options, |
|
RequestInterceptorHandler handler, |
|
) async { |
|
final String? token = _tokenRepository.access; |
|
if (token != null && token.isNotEmpty) { |
|
options.headers.addAll( |
|
<String, String>{ |
|
'Authorization': 'Bearer $token', |
|
}, |
|
); |
|
} |
|
handler.next(options); |
|
} |
|
|
|
@override |
|
void onError(DioError err, ErrorInterceptorHandler handler) async { |
|
if (err.response?.statusCode == 401) { |
|
final refreshToken = _tokenRepository.refresh; |
|
if (refreshToken == null || refreshToken.isEmpty) { |
|
_tokenRepository.clear(); |
|
_authorizationRepository.reauthorize(); |
|
return handler.next(err); |
|
} |
|
try { |
|
final AuthenticationEntity authenticationEntity = |
|
await _refreshTokenRepository.refresh(refreshToken); |
|
await _tokenRepository.update( |
|
access: authenticationEntity.accessToken, |
|
refresh: authenticationEntity.refreshToken, |
|
); |
|
final RequestOptions requestOptions = err.response!.requestOptions; |
|
requestOptions.headers['Authorization'] = |
|
'Bearer ${authenticationEntity.accessToken}'; |
|
final options = Options( |
|
method: requestOptions.method, |
|
headers: requestOptions.headers, |
|
); |
|
final Dio dioRefresh = Dio( |
|
BaseOptions( |
|
baseUrl: requestOptions.baseUrl, |
|
headers: <String, String>{ |
|
'accept': 'application/json', |
|
}, |
|
), |
|
); |
|
final response = await dioRefresh.request<dynamic>( |
|
requestOptions.path, |
|
data: requestOptions.data, |
|
queryParameters: requestOptions.queryParameters, |
|
options: options, |
|
); |
|
return handler.resolve(response); |
|
} on DioError { |
|
if (err.response?.statusCode == 401) { |
|
await _tokenRepository.clear(); |
|
await _authorizationRepository.reauthorize(); |
|
} |
|
} |
|
} |
|
handler.next(err); |
|
} |
|
} |
When I fire two GQL requests in the same component, both requests try to refresh the tokens. There doesn't seem to be logic here to let the second request understand that the first request already refreshed the token.