I have a ViewPager
and three webservice calls are made when ViewPager
is loaded simultaneously.
When first one returns 401, Authenticator
is called and I refresh the token inside Authenticator
, but remaining 2 requests are already sent to the server with old refresh token and fails with 498 which is captured in Interceptor and app is logged out.
This is not the ideal behaviour I would expect. I would like to keep the 2nd and 3rd request in the queue and when the token is refreshed, retry the queued request.
Currently, I have a variable to indicate if token refresh is ongoing in Authenticator
, in that case, I cancel all subsequent request in the Interceptor
and user has to manually refresh the page or I can logout the user and force user to login.
What is a good solution or architecture for the above problem using okhttp 3.x for Android?
EDIT: The problem I want to solve is in general and I would not like to sequence my calls. i.e. wait for one call to finish and refresh the token and then only send rest of the request on the activity and fragment level.
Code was requested. This is a standard code for Authenticator
:
public class CustomAuthenticator implements Authenticator {
@Inject AccountManager accountManager;
@Inject @AccountType String accountType;
@Inject @AuthTokenType String authTokenType;
@Inject
public ApiAuthenticator(@ForApplication Context context) {
}
@Override
public Request authenticate(Route route, Response response) throws IOException {
// Invaidate authToken
String accessToken = accountManager.peekAuthToken(account, authTokenType);
if (accessToken != null) {
accountManager.invalidateAuthToken(accountType, accessToken);
}
try {
// Get new refresh token. This invokes custom AccountAuthenticator which makes a call to get new refresh token.
accessToken = accountManager.blockingGetAuthToken(account, authTokenType, false);
if (accessToken != null) {
Request.Builder requestBuilder = response.request().newBuilder();
// Add headers with new refreshToken
return requestBuilder.build();
} catch (Throwable t) {
Timber.e(t, t.getLocalizedMessage());
}
}
return null;
}
}
Some questions similar to this: OkHttp and Retrofit, refresh token with concurrent requests