Access token expiration. Refresh Token. Retrofit Interceptor, Coroutines
--
I will bring an example of implementation in Kotlin for handling token expiration and refreshing the access token using Retrofit and Coroutines:
First, create an API interface for the token refresh request:
interface ApiService {
@POST("/api/v1/users/refresh-token/")
suspend fun refreshAccessToken(): TokenResponse
}
Create a TokenResponse
data class to represent the response from the token refresh endpoint:
data class TokenResponse(
@SerializedName("access_token") val accessToken: String,
@SerializedName("expires_in") val expiresIn: Long
)
Next, you can implement the token refresh logic in your network interceptor or authentication manager class:
class AuthInterceptor(private val apiService: ApiService) : Interceptor {
// Other interceptor configuration and properties
private val sessionManager = SessionManager() // Replace with your session management class
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val accessToken = sessionManager.getAccessToken()
if (accessToken != null && sessionManager.isAccessTokenExpired()) {
val refreshToken = sessionManager.getRefreshToken()
// Make the token refresh request
val refreshedToken = runBlocking {
val response = apiService.refreshAccessToken()
// Update the refreshed access token and its expiration time in the session
sessionManager.updateAccessToken(response.accessToken, response.expiresIn)
response.accessToken
}
if (refreshedToken != null) {
// Create a new request with the refreshed access token
val newRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer $refreshedToken")
.build()
// Retry the request with the new access token
return chain.proceed(newRequest)
}
}
// Add the access token to the request header
val authorizedRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer $accessToken")
.build()
return chain.proceed(authorizedRequest)
}
}
n this example, SessionManager
is a class that manages the access token and its expiration time. The isAccessTokenExpired()
method checks if the access token has expired based on the current time and the token's expiration time stored in the session. The getAccessToken()
and getRefreshToken()
methods retrieve the access token and refresh token from the session, respectively. The updateAccessToken()
method updates the access token and its expiration time in the session after a successful token refresh.
Make sure to configure Retrofit with the AuthInterceptor
when building the OkHttpClient
:
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(AuthInterceptor(apiService))
// Other OkHttpClient configuration
.build()
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
// Other Retrofit configuration
.build()
With this implementation, whenever an API request receives a 401 unauthorized response due to an expired access token, the interceptor will automatically trigger the token refresh request, update the access token in the session, and retry the original request with the refreshed access token.
Here’s an example implementation of the isAccessTokenExpired()
method in SessionManager
class:
class SessionManager {
// Other session management properties and methods
private var accessToken: String? = null
private var accessTokenExpirationTime: Long? = null
// Method to check if the access token has expired
fun isAccessTokenExpired(): Boolean {
val currentTimeMillis = System.currentTimeMillis()
return accessTokenExpirationTime != null && currentTimeMillis >= accessTokenExpirationTime!!
}
// Method to update the access token and its expiration time in the session
fun updateAccessToken(token: String, expiresIn: Long) {
accessToken = token
accessTokenExpirationTime = System.currentTimeMillis() + expiresIn * 1000 // Convert expiresIn to milliseconds
}
// Other session management methods
}
In this example, accessToken
is the stored access token, and accessTokenExpirationTime
represents the expiration time of the access token. The isAccessTokenExpired()
method compares the current time (currentTimeMillis
) with the expiration time to determine if the access token has expired. If accessTokenExpirationTime
is not null and the current time is greater than or equal to the expiration time, it indicates that the access token has expired.
The updateAccessToken()
method is responsible for updating the access token and its expiration time in the session after a successful token refresh or initial login. It takes the new access token (token
) and the expiration time in seconds (expiresIn
), converts the expiration time to milliseconds, and stores the updated values in the accessToken
and accessTokenExpirationTime
properties.