Retrofit - Handle Refresh Token Expiration

When my app's Access Token is expired, I use Refresh Token to get a new Access Token through Authenticator class.

My code follows:

if (response.code() == 401) {
   Log.d("refresh", "Access token expired")
   val webservice: Webservice = RetrofitClient.makeRetrofitService().create(
   var refreshToken = PreferenceData.getUserLoggedInRefreshToken(App.GetContext()!!)
   var map = generateRequestBody(mapOf("refreshToken" to refreshToken!!))
   var refreshResponse = webservice.refreshToken(map).execute()

   if (refreshResponse != null && refreshResponse.code() == 200) {
      Log.d("refresh", "New access token received")
      var newToken = (refreshResponse.body() as UserLogin).token
      var refreshToken = (refreshResponse.body() as UserLogin).refreshToken
      PreferenceData.setUserLoggedInAccessToken(App.GetContext()!!, newToken)
      PreferenceData.setUserLoggedInRefreshToken(App.GetContext()!!, refreshToken)

      return response.request().newBuilder()
      .header("Authorization", "Bearer $newToken")

So far so good. What I want to do now is when my Refresh Token is expired, I would like to redirect user to app's login screen. But my problem is, when I call

var refreshResponse = webservice.refreshToken(map).execute()

server also returns 401. So my problem is I cannot tell whether the 401 I received is due to Access Token being expired or Refresh Token being expired. What's the most suitable way to handle this problem?




You can take a look at AppAuth-Android implementation.

  1. Before doing any call you can check that you still have a valid access token, getting its expiration time and comparing it with the result from clock.getCurrentTimeMillis().

  2. Just in case the access token is invalid for other reasons (e.g. the access token can be manually revoked), you can use an Okhttp Interceptor to react to 401s.

  3. If the access token is expired or if you get a 401, you can try to refresh the access token with your refresh token.

  4. If the refresh token is not valid anymore, the /token endpoint will return the following error:

HTTP/1.1 400 Bad Request { "error":"invalid_request" }

  1. If you get that error, you can logout the user and send him the app's login screen.

Hope it helps you.