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.