Suas ideias em realidade digital!
Quando usamos JWT, o token normalmente expira em poucos minutos. Sem refresh automático, o usuário precisaria fazer login novamente.
A solução é implementar um Interceptor que detecta erro 401 e automaticamente solicita um novo token.
data class AuthResponse(
val token: String,
val refresh_token: String,
val expires_in: Int
)
object TokenManager {
private const val PREF_NAME = "auth_prefs"
private const val KEY_TOKEN = "token"
private const val KEY_REFRESH = "refresh"
fun save(context: Context, token: String, refresh: String) {
val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
prefs.edit().apply {
putString(KEY_TOKEN, token)
putString(KEY_REFRESH, refresh)
apply()
}
}
fun getToken(context: Context): String? {
return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getString(KEY_TOKEN, null)
}
fun getRefresh(context: Context): String? {
return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getString(KEY_REFRESH, null)
}
}
class AuthInterceptor(
private val context: Context
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val token = TokenManager.getToken(context)
val request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer $token")
.build()
return chain.proceed(request)
}
}
class RefreshInterceptor(
private val context: Context,
private val apiService: ApiService
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val response = chain.proceed(request)
if (response.code == 401) {
synchronized(this) {
val refreshToken = TokenManager.getRefresh(context)
val refreshResponse = apiService.refreshToken(refreshToken!!)
.execute()
if (refreshResponse.isSuccessful) {
val newToken = refreshResponse.body()?.token
val newRefresh = refreshResponse.body()?.refresh_token
TokenManager.save(context, newToken!!, newRefresh!!)
request = request.newBuilder()
.header("Authorization", "Bearer $newToken")
.build()
return chain.proceed(request)
}
}
}
return response
}
}
Seu backend deve ter algo como:
POST /auth/refresh
Veja implementação completa aqui: