Handle call retry up to 3 time when statusCode=401
(cherry picked from commit 09a93eff116a1dffc6a59ab97226a86cba47998e)
This commit is contained in:
@@ -15,6 +15,9 @@ import 'package:tmail_ui_user/features/login/data/network/authentication_client/
|
|||||||
|
|
||||||
class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||||
|
|
||||||
|
static const int _maxRetryCount = 3;
|
||||||
|
static const String RETRY_KEY = 'Retry';
|
||||||
|
|
||||||
final Dio _dio;
|
final Dio _dio;
|
||||||
final AuthenticationClientBase _authenticationClient;
|
final AuthenticationClientBase _authenticationClient;
|
||||||
final TokenOidcCacheManager _tokenOidcCacheManager;
|
final TokenOidcCacheManager _tokenOidcCacheManager;
|
||||||
@@ -41,7 +44,6 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
|||||||
_token = newToken;
|
_token = newToken;
|
||||||
_configOIDC = newConfig;
|
_configOIDC = newConfig;
|
||||||
_authenticationType = AuthenticationType.oidc;
|
_authenticationType = AuthenticationType.oidc;
|
||||||
log('AuthorizationInterceptors::setToken(): newToken: $newToken | configOIDC: $_configOIDC');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateNewToken(Token newToken) {
|
void _updateNewToken(Token newToken) {
|
||||||
@@ -54,6 +56,8 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||||
|
log('AuthorizationInterceptors::onRequest():DATA: ${options.data}');
|
||||||
|
log('AuthorizationInterceptors::onRequest():TOKEN_HASHCODE_CURRENT: ${_token?.token.hashCode}');
|
||||||
switch(_authenticationType) {
|
switch(_authenticationType) {
|
||||||
case AuthenticationType.basic:
|
case AuthenticationType.basic:
|
||||||
if (_authorization != null) {
|
if (_authorization != null) {
|
||||||
@@ -73,77 +77,87 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onError(DioError err, ErrorInterceptorHandler handler) async {
|
void onError(DioError err, ErrorInterceptorHandler handler) async {
|
||||||
logError('AuthorizationInterceptors::onError():dioType: ${err.type} | statusCode: ${err.response?.statusCode} | message: ${err.message} | statusMessage: ${err.response?.statusMessage}');
|
logError('AuthorizationInterceptors::onError(): $err');
|
||||||
try {
|
logError('AuthorizationInterceptors::onError():TOKEN_HASHCODE_CURRENT: ${_token?.token.hashCode}');
|
||||||
if (_validateToRefreshToken(err)) {
|
|
||||||
log('AuthorizationInterceptors::onError:RefreshTokenCalled:configOIDC: $_configOIDC | refreshTokenCurrent: ${_token?.refreshToken}');
|
|
||||||
final newToken = await _authenticationClient.refreshingTokensOIDC(
|
|
||||||
_configOIDC!.clientId,
|
|
||||||
_configOIDC!.redirectUrl,
|
|
||||||
_configOIDC!.discoveryUrl,
|
|
||||||
_configOIDC!.scopes,
|
|
||||||
_token!.refreshToken
|
|
||||||
);
|
|
||||||
|
|
||||||
final accountCurrent = await _accountCacheManager.getSelectedAccount();
|
final requestOptions = err.requestOptions;
|
||||||
|
final extraInRequest = requestOptions.extra;
|
||||||
|
var retries = extraInRequest[RETRY_KEY] ?? 0;
|
||||||
|
|
||||||
await _accountCacheManager.deleteSelectedAccount(_token!.tokenIdHash);
|
if (_validateToRefreshToken(err)) {
|
||||||
|
log('AuthorizationInterceptors::onError:>> _validateToRefreshToken');
|
||||||
|
final newToken = await _authenticationClient.refreshingTokensOIDC(
|
||||||
|
_configOIDC!.clientId,
|
||||||
|
_configOIDC!.redirectUrl,
|
||||||
|
_configOIDC!.discoveryUrl,
|
||||||
|
_configOIDC!.scopes,
|
||||||
|
_token!.refreshToken
|
||||||
|
);
|
||||||
|
|
||||||
await Future.wait([
|
final accountCurrent = await _accountCacheManager.getSelectedAccount();
|
||||||
_tokenOidcCacheManager.persistOneTokenOidc(newToken),
|
|
||||||
_accountCacheManager.setSelectedAccount(
|
await _accountCacheManager.deleteSelectedAccount(_token!.tokenIdHash);
|
||||||
PersonalAccount(
|
|
||||||
newToken.tokenIdHash,
|
await Future.wait([
|
||||||
AuthenticationType.oidc,
|
_tokenOidcCacheManager.persistOneTokenOidc(newToken),
|
||||||
isSelected: true,
|
_accountCacheManager.setSelectedAccount(
|
||||||
accountId: accountCurrent.accountId,
|
PersonalAccount(
|
||||||
apiUrl: accountCurrent.apiUrl,
|
newToken.tokenIdHash,
|
||||||
userName: accountCurrent.userName
|
AuthenticationType.oidc,
|
||||||
)
|
isSelected: true,
|
||||||
|
accountId: accountCurrent.accountId,
|
||||||
|
apiUrl: accountCurrent.apiUrl,
|
||||||
|
userName: accountCurrent.userName
|
||||||
)
|
)
|
||||||
]);
|
)
|
||||||
log('AuthorizationInterceptors::onError():NewToken: $newToken');
|
]);
|
||||||
_updateNewToken(newToken.toToken());
|
_updateNewToken(newToken.toToken());
|
||||||
|
|
||||||
final requestOptions = err.requestOptions;
|
final requestOptions = err.requestOptions;
|
||||||
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token);
|
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(newToken.token);
|
||||||
|
|
||||||
final response = await _dio.fetch(requestOptions);
|
final response = await _dio.fetch(requestOptions);
|
||||||
return handler.resolve(response);
|
return handler.resolve(response);
|
||||||
} else {
|
} else if (_validateToRetry(err, retries)) {
|
||||||
super.onError(err, handler);
|
log('AuthorizationInterceptors::onError:>> _validateToRetry | retries: $retries');
|
||||||
}
|
retries++;
|
||||||
} catch (e) {
|
|
||||||
logError('AuthorizationInterceptors::onError():Exception: $e');
|
final requestOptions = err.requestOptions;
|
||||||
|
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(_token!.token);
|
||||||
|
requestOptions.extra = {RETRY_KEY: retries};
|
||||||
|
|
||||||
|
final response = await _dio.fetch(requestOptions);
|
||||||
|
return handler.resolve(response);
|
||||||
|
} else {
|
||||||
super.onError(err, handler);
|
super.onError(err, handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isTokenExpired() {
|
bool _isTokenExpired() => _token?.isExpired == true;
|
||||||
if (_token?.isExpired == true) {
|
|
||||||
log('AuthorizationInterceptors::_isTokenExpired(): TOKE_EXPIRED');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _isAuthenticationOidcValid() {
|
bool _isAuthenticationOidcValid() => _authenticationType == AuthenticationType.oidc && _configOIDC != null;
|
||||||
if (_authenticationType == AuthenticationType.oidc &&
|
|
||||||
_configOIDC != null &&
|
|
||||||
_token != null) {
|
|
||||||
log('AuthorizationInterceptors::_isAuthenticationOidcValid()');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _isRefreshTokenNotEmpty() => _token != null && _token!.refreshToken.isNotEmpty;
|
bool _isTokenNotEmpty() => _token?.token.isNotEmpty == true;
|
||||||
|
|
||||||
|
bool _isRefreshTokenNotEmpty() => _token?.refreshToken.isNotEmpty == true;
|
||||||
|
|
||||||
bool _validateToRefreshToken(DioError dioError) {
|
bool _validateToRefreshToken(DioError dioError) {
|
||||||
if (_isTokenExpired() &&
|
if (dioError.response?.statusCode == 401 &&
|
||||||
(dioError.response == null || dioError.response?.statusCode == 401) &&
|
_isAuthenticationOidcValid() &&
|
||||||
_isRefreshTokenNotEmpty() &&
|
_isRefreshTokenNotEmpty() &&
|
||||||
_isAuthenticationOidcValid()) {
|
_isTokenExpired()
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _validateToRetry(DioError dioError, int retryCount) {
|
||||||
|
if (dioError.type == DioErrorType.badResponse &&
|
||||||
|
dioError.response?.statusCode == 401 &&
|
||||||
|
_isTokenNotEmpty() &&
|
||||||
|
retryCount < _maxRetryCount
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user