Android Retrofit 2.0 Refresh Tokens Android Retrofit 2.0 Refresh Tokens android android

Android Retrofit 2.0 Refresh Tokens


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.


The authenticate() method is called when the server returns 401 Unauthorized.

For calling ApiFactory.retrofit("url").create(PostDataInterface::class.java).refreshToken(refreshTokenRequest)), we're using execute() to make it a synchronous call.

if refresh token status is 0. Add your function to logout the user.

interface PostDataInterface {@POST("refreshUserToken")fun refreshToken(@Body refreshTokenRequest: RefreshTokenRequest?): Call<RefreshTokenResponse?>?

}

class TokenAuthenticator : Authenticator {override fun authenticate(route: Route?, response: Response): Request? {    // This is a synchronous call    val updatedToken = getNewToken()    return updatedToken?.let {        response.request.newBuilder().header("Authorization", it)            .build()    }}private fun getNewToken(): String? {    val refreshTokenRequest = RefreshTokenRequest(SharedPreferenceHelper.refreshToken)    val call = ApiFactory.retrofit(BuildConfig.BASEURL).create(PostDataInterface::class.java)        .refreshToken(refreshTokenRequest)    val authTokenResponse = call?.execute()?.body()    if (authTokenResponse?.status == 0){        //Logout User        AuthUtility.logout(true)    }    return authTokenResponse?.data?.token}}

Add Authenticator in Okhttp client

private val client =        OkHttpClient().newBuilder()            .authenticator(TokenAuthenticator())            ...            .build()  


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.