Android Retrofit 2.0 Refresh Tokens

Here is the refresh token authenticator implementation

class TokenAuthenticator(
    val sharedPrefsHelper: SharedPrefsHelper,
    private val identityService: IdentityService
) : Authenticator {

    override fun authenticate(route: Route?, response: Response): Request? {
        Log.d("TokenAuth Request:", "${response.body}")
        val refreshToken = sharedPrefsHelper[SharedPrefsHelper.PREF_KEY_AUTH_REFRESH_TOKEN, null]
        if (refreshToken.isNullOrEmpty().not()) {
            val requestFields = mutableMapOf<String, String>()
            requestFields["refresh_token"] = refreshToken!!
            requestFields["grant_type"] = "refresh_token"
            try {
                val tokenResponse = runBlocking {
                    identityService.getAuthToken(requestFields)
                }
                Log.d("TokenAuth Success:", "$tokenResponse")
                tokenResponse.accessToken.let { accessToken ->
                    sharedPrefsHelper.put(
                        SharedPrefsHelper.PREF_KEY_AUTH_TOKEN,
                        accessToken
                    )
                    sharedPrefsHelper.put(
                        SharedPrefsHelper.PREF_KEY_AUTH_REFRESH_TOKEN,
                        tokenResponse.refreshToken
                    )

                    return response.request.newBuilder()
                        .header("Authorization", "Bearer $accessToken")
                        .build()
                }
            } catch (e: Exception) {
                Log.d("TokenAuth Error:", "$e")
            }
        }
        return null
    }
}

Configure it with the builder -

  return OkHttpClient.Builder()
            .authenticator(TokenAuthenticator(sharedPrefsHelper, identityBaseUrl))
            .addInterceptor(httpLoggingInterceptor)
            .addInterceptor(requestInterceptor).addInterceptor(logging)
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .build()

And also as @Yasin suggested -

Don't forget to return null or put any try limit. If you don't limit, it will try to refresh multiple times when your refresh request fails. Also, make synchronous requests when refreshing your token.


I searched this topic since 2-3 months ago and found OkHttp's Authenticator. You can use it. There is one link here: refreshing-oauth-token-using-retrofit-without-modifying-all-calls

It works like that: If your request returns 401, then Authenticator moves in, and refreshes your token. But don't forget to return null or put any try limit. If you don't limit, it will try to refresh multiple times when your refresh request fails. Also, make synchronous requests when refreshing your token.

Also, I have a question and answer -both written by myself- about refreshing the Oauth2 token:

Question: android-retrofit2-refresh-oauth-2-token

Answer: android-retrofit2-refresh-oauth-2-token-answer

Additionally: For example if you have a token and you need to refresh it per 3 hours. You can write an Interceptor too. In Interceptor: compare time and refresh your token without getting any 401 response.

Square's documentation for Interceptor: OkHttp Interceptors

Square's documentation for Authenticator: OkHttp handling-authentication

I know there is no code here, but see links and edit your question then I will try to help you.