@NonNull private AuthResponse refreshAccessToken(AuthResponse currentAuth) throws IOException, HttpResponseStatusException { OkHttpClient client = OkHttpUtil.getClient(context); Retrofit retrofit = new Retrofit.Builder() .client(client) .baseUrl(config.getApiHostURL()) .addConverterFactory(GsonConverterFactory.create()) .build(); LoginService loginService = retrofit.create(LoginService.class); retrofit2.Response<AuthResponse> refreshTokenResponse; refreshTokenResponse = loginService .refreshAccessToken( "refresh_token", config.getOAuthClientId(), currentAuth.refresh_token) .execute(); if (!refreshTokenResponse.isSuccessful()) { throw new HttpResponseStatusException(refreshTokenResponse.code()); } AuthResponse refreshTokenData = refreshTokenResponse.body(); loginPrefs.storeRefreshTokenResponse(refreshTokenData); return refreshTokenData; }
@Override public synchronized Request authenticate(Route route, final Response response) throws IOException { logger.warn(response.toString()); final AuthResponse currentAuth = loginPrefs.getCurrentAuth(); if (null == currentAuth || null == currentAuth.refresh_token) { return null; } String errorCode = getErrorCode(response.peekBody(200).string()); if (errorCode != null) { switch (errorCode) { case TOKEN_EXPIRED_ERROR_MESSAGE: final AuthResponse refreshedAuth; try { refreshedAuth = refreshAccessToken(currentAuth); } catch (HttpResponseStatusException e) { return null; } return response .request() .newBuilder() .header("Authorization", refreshedAuth.token_type + " " + refreshedAuth.access_token) .build(); case TOKEN_NONEXISTENT_ERROR_MESSAGE: case TOKEN_INVALID_GRANT_ERROR_MESSAGE: // Retry request with the current access_token if the original access_token used in // request does not match the current access_token. This case can occur when // asynchronous calls are made and are attempting to refresh the access_token where // one call succeeds but the other fails. https://github.com/edx/edx-app-android/pull/834 if (!response .request() .headers() .get("Authorization") .split(" ")[1] .equals(currentAuth.access_token)) { return response .request() .newBuilder() .header("Authorization", currentAuth.token_type + " " + currentAuth.access_token) .build(); } } } return null; }