Authenticator in Retrofit Android
Tags: retrofit, token, android, authentication
Published: 2019-11-27 14:36:14

---
title: Authenticator in Retrofit Android
published: true
cover_image: https://thepracticaldev.s3.amazonaws.com/i/utusdi21fielckssugr8.jpeg
description: Refresh Authentication Token in Retrofit without modifying any call
tags: retrofit, token, android, authentication
---

There is a general use-case in any application that the authentication token expires, and you need to refresh the internally. After upgrading the token, the API call should be executed again, and UI should be updated. Let's understand this scenario by an example:
- You are building a social network application which has various functionalities, i.e. new feeds, friend requests list, send a friend request, see comments on a post etc.
- After login, you provide an authentication token(i.e. JWT token) to the user. This token has an expiry time of 10 mins(which could be dynamic at server-side), and this should be passed in the header of each API call.
- When you go to the friend requests list screen, you get `401 Unauthorized` which means you need to refresh the token.
- You not only need to update the token but also make the call to friend requests list API again and show the list in UI.

The naive way of handling this is, on each API call, make a check of 401 status code and call the refresh token API again. After calling the API, make the call to required API again. This code needs to be written everywhere(i.e. in each API call callback).

Does Android(more specific, Retrofit) have any way to handle this scenario using a standard code?
The answer is *YES!!!* We have a way of handling this scenario in `Retrofit` using `Authenticator`.

You can achieve this functionality using simple steps which are described below:
## 1. Method to fetch updated token
Declare a method in the retrofit interface to fetch the updated token from the server, as shown below:
```kotlin
interface UserApiService {
    companion object {
        private const val REQUEST_REFRESH_TOKEN = "/oauth/token"
    }

    @FormUrlEncoded
    @POST(REQUEST_REFRESH_TOKEN)
    fun getAuthenticationToken(@FieldMap params: HashMap<String, String>): retrofit2.Call<AuthTokenResponse>

    ...
}
```
## 2. Create an Authenticator class
Implemented `okhttp3.Authenticator` interface and override `authenticate()` method as shown below:
```kotlin
class TokenAuthenticator : Authenticator {
    override fun authenticate(route: Route?, response: Response): Request? {
        // This is a synchronous call
        val updatedToken = getUpdatedToken()
        return response.request().newBuilder()
                .header(ApiClient.HEADER_AUTHORIZATION, updatedToken)
                .build()
    }

    private fun getUpdatedToken(): String {
        val requestParams = HashMap<String, String>()
        ...

        val authTokenResponse = ApiClient.userApiService.getAuthenticationToken(requestParams).execute().body()!!

        val newToken = "${authTokenResponse.tokenType} ${authTokenResponse.accessToken}"
        SharedPreferenceUtils.saveString(Constants.PreferenceKeys.USER_ACCESS_TOKEN, newToken)
        return newToken
    }
}
```
 The `authenticate()` method is called when server returns `401 Unauthorized`. For calling `ApiClient.userApiService.getAuthenticationToken()`, we're using `execute()` to make it a synchronous call.

 
## 3. Prepare OkHttp client
 Now set this `TokenAuthenticator` in `OkHttpClient` as shown below:
 ```kotlin
 OkHttpClient.Builder()
                .connectTimeout(TIMEOUT_IN_SECONDS.toLong(), TimeUnit.SECONDS)
                .readTimeout(TIMEOUT_IN_SECONDS.toLong(), TimeUnit.SECONDS)
                .authenticator(TokenAuthenticator())`
                .addInterceptor(MyInterceptor())
 ```

*That is it!!!*
Now, whenever you make an API call, i.e. friend requests list API call and get 401, the retrofit will call API to refresh the token and make the same request, i.e. friend requests list call again.
You do not need to handle anything on the view layer for this.

Thanks for reading this article. I hope you liked it and understood the solution easily. For any doubts or suggestions, feel free to comment.
If you're new to Kotlin, you can read my previous blog [Features You Will Love About Kotlin](https://dev.to/mohitrajput987/features-you-will-love-about-kotlin-h8o) which will give you the understanding of this beautiful language.