Auto-refresh auth token on 401

This commit is contained in:
androidlover5842
2026-01-28 04:50:20 +05:30
parent d8a40e4c9a
commit d2d60b5074
3 changed files with 21 additions and 4 deletions

View File

@@ -1,6 +1,7 @@
package com.android.trisolarispms.data.api package com.android.trisolarispms.data.api
import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.FirebaseAuth
import okhttp3.Authenticator
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
@@ -18,7 +19,7 @@ object ApiClient {
val authInterceptor = Interceptor { chain -> val authInterceptor = Interceptor { chain ->
val original = chain.request() val original = chain.request()
val token = try { val token = try {
kotlinx.coroutines.runBlocking { tokenProvider.token() } kotlinx.coroutines.runBlocking { tokenProvider.token(forceRefresh = false) }
} catch (e: Exception) { } catch (e: Exception) {
null null
} }
@@ -32,12 +33,28 @@ object ApiClient {
chain.proceed(request) chain.proceed(request)
} }
val authenticator = Authenticator { _, response ->
if (response.code != 401) return@Authenticator null
if (response.request.header("X-Auth-Retry") == "true") return@Authenticator null
val newToken = try {
kotlinx.coroutines.runBlocking { tokenProvider.token(forceRefresh = true) }
} catch (e: Exception) {
null
}
if (newToken.isNullOrBlank()) return@Authenticator null
response.request.newBuilder()
.header("Authorization", "Bearer $newToken")
.header("X-Auth-Retry", "true")
.build()
}
val logging = HttpLoggingInterceptor().apply { val logging = HttpLoggingInterceptor().apply {
level = if (enableLogging) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE level = if (enableLogging) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
} }
val client = OkHttpClient.Builder() val client = OkHttpClient.Builder()
.addInterceptor(authInterceptor) .addInterceptor(authInterceptor)
.authenticator(authenticator)
.addInterceptor(logging) .addInterceptor(logging)
.connectTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)

View File

@@ -1,5 +1,5 @@
package com.android.trisolarispms.data.api package com.android.trisolarispms.data.api
interface AuthTokenProvider { interface AuthTokenProvider {
suspend fun token(): String? suspend fun token(forceRefresh: Boolean = false): String?
} }

View File

@@ -6,8 +6,8 @@ import kotlinx.coroutines.tasks.await
class FirebaseAuthTokenProvider( class FirebaseAuthTokenProvider(
private val auth: FirebaseAuth private val auth: FirebaseAuth
) : AuthTokenProvider { ) : AuthTokenProvider {
override suspend fun token(): String? { override suspend fun token(forceRefresh: Boolean): String? {
val user = auth.currentUser ?: return null val user = auth.currentUser ?: return null
return user.getIdToken(false).await().token return user.getIdToken(forceRefresh).await().token
} }
} }