refreshToken method
Performs a coordinated token refresh.
If a refresh is already in progress, this will return the same future that the in-flight refresh will complete with. This ensures that concurrent refresh requests result in only one actual refresh operation.
Additionally, if the token has already been refreshed by a previous
request (detected by comparing with tokenUsedForRequest), this will
return the current token without triggering a new refresh.
The tokenUsedForRequest parameter should be the token value that was
used when the request that triggered this refresh was made. This allows
detection of cases where another request has already refreshed the token.
If the refresh succeeds, the new token is automatically saved via
setToken and returned.
If the refresh fails:
- If a RevokeTokenException is thrown,
clearTokenis called and the exception is rethrown. - For any other exception, the exception is rethrown without clearing the token.
In all cases (success or failure), the in-flight refresh state is
cleared in a finally block, ensuring no deadlocks.
Implementation
Future<T> refreshToken({
T? tokenUsedForRequest,
}) async {
// Check if we already have a different token than what was used for the
// request. This means another request already refreshed the token.
if (_token != tokenUsedForRequest) {
// Token has already been refreshed, return the current token
if (_token != null) {
return _token as T;
}
}
// If a refresh is already in progress, await it
final existingFuture = _refreshFuture;
if (existingFuture != null) {
return existingFuture;
}
// Start a new refresh - create and store the future immediately
// before any await to prevent race conditions
final future = _doRefresh();
_refreshFuture = future;
return future;
}