Loading
Please wait, content is loading
Logo Black Logo White
  • Portfolio
  • About
  • Stories
  • Contact
Menu

Recent Posts

  • Android – API Interceptor
  • Retrofit Logging Interceptor

Recent Comments

No comments to show.
Recent Posts
  • Android – API Interceptor
  • Retrofit Logging Interceptor
Recent Comments
No comments to show.
  • February 26, 2025

Android – API Interceptor

  • Android
  • Kotlin
  • Mobile
Post Image

API controllers exist in 99% of the applications worlwide. Most developers are very familiar with APIs and server mechanisms. What happens when it comes to auth session though?

The problem

Imagine you have a OAuth2 token (access & refresh tokens) retrieved from a login request. The access token expires every 1 hour and refresh token every 14 days. Now, let’s say that you are trying to perform an API request at the exact moment the access token expires!

The common way

Most developers would check here if the access token is valid. If the token is valid it will be used to complete the request. If not, the refresh token would be used to refresh the access token before proceeding to the request. But wait… This is not the way right? Exactly!

The solution

In this case we use the famous Authenticators. An authenticator is an interface implementation that is injected at your API client and performs all these checks before any request is performed. If the access token requires an update, the interceptor will perform that update. Let’s see an example:

The authenticator interface has 1 function, the authenticate:

fun authenticate(route: Route?, response: Response): Request?

Here, we can check whether the tokens are valid and return the request or null if we can not authenticate it. Notice that authenticate will only be called when a request requires authentication. Let’s see a full implementation:

override fun authenticate(route: Route?, response: Response): Request? {

    logger.d("[${javaClass.name}] :: Request needs authentication. Starting process.")

    synchronized(this) {

    // Get tokens.
    val accessToken = authController.getAccessToken()
    val refreshToken = authController.getRefreshToken()

    if (!accessToken.isNullOrEmpty() && response.request.header("Authorization") == null) {
        logger.d("[${javaClass.name}] :: Access token is valid. Adding as header.")
        return response.request.newBuilder()
            .header("Authorization", accessToken)
            .build()
     } else if (!refreshToken.isNullOrEmpty()) {
        logger.d("[${javaClass.name}] :: Access token is invalid. Refreshing token.")
        return runBlocking {
            // Try to refresh token.
            when (interactor.refreshToken()) {
                is AzureRefreshPartialState.Success -> {
                    response.request.newBuilder()
                        .header("Authorization", authController.getAccessToken() ?: "")
                        .build()
                 }
                 is AzureRefreshPartialState.Failed -> {
                     onCanNotAuthenticate(context, authController)
                     null
                  }
             }
         }
      }

      logger.e("[${javaClass.name}] :: Both access & refresh tokens are invalid.")

      // Can not satisfy challenge.
      onCanNotAuthenticate(context, authController)

    }

    return null
}

We can now build our OkHttp client using the following code and the authenticator will do it’s job:

return OkHttpClient.Builder()
    .authenticator(apiAuthenticator)
    .addInterceptor(apiInterceptor)
    .addInterceptor(httpLoggingInterceptor)
    .addInterceptor(CurlInterceptor {
        logger.d("curl :: $it")
    })
    .readTimeout(API_TIMEOUT, TimeUnit.SECONDS)
    .connectTimeout(API_TIMEOUT, TimeUnit.SECONDS)
    .build()
Files

OkHttp-AuthenticatorDownload

Prev
No more posts
Next
Retrofit Logging Interceptor
  • No Comments
  • Leave a comment
Cancel Reply

Back Top
2025 © VGraphics IKE. All rights reserved.

Gemi 181823306000 • George Vergidis (100%/500€)

Follow Us
  • Ld