Skip to content

Instantly share code, notes, and snippets.

@TimurMukhortov
Last active May 16, 2024 19:18
Show Gist options
  • Save TimurMukhortov/a1c9819e3779015e54bc3964b7d2308a to your computer and use it in GitHub Desktop.
Save TimurMukhortov/a1c9819e3779015e54bc3964b7d2308a to your computer and use it in GitHub Desktop.
Dio authorization Interceptor with QueuedInterceptorsWrapper
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);
}
}
@x-ji
Copy link

x-ji commented May 16, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment