Handling API 403 and 401 Unauthorized errors is essential when building secure Kotlin Android applications that rely on web services. These HTTP status codes indicate that the user is either unauthorized (401) or forbidden (403) to access a resource, usually due to invalid credentials or missing access tokens.
In Kotlin-based Android development using Retrofit
, the best practice is to intercept these responses, notify the user, and redirect them to login or token refresh logic.
Here is a complete working example to handle 401/403 API errors using Retrofit and OkHttp interceptor in Kotlin.
Step 1: Add Retrofit & OkHttp dependencies (in build.gradle
):
implementation "com.squareup.retrofit2:retrofit:2.9.0" implementation "com.squareup.okhttp3:logging-interceptor:4.9.1"
Step 2: Create an AuthInterceptor.kt
class AuthInterceptor(private val tokenProvider: () -> String?) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val token = tokenProvider() val request = chain.request().newBuilder() .apply { if (!token.isNullOrEmpty()) { header("Authorization", "Bearer $token") } } .build() val response = chain.proceed(request) if (response.code == 401 || response.code == 403) { // You can log out the user or refresh token here println("Unauthorized or Forbidden. Code: ${response.code}") } return response } }
Step 3: Create Retrofit Instance (ApiClient.kt
)
object ApiClient { private val retrofit: Retrofit init { val client = OkHttpClient.Builder() .addInterceptor(AuthInterceptor { getTokenFromPrefs() }) .build() retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() } fun <T> create(service: Class<T>): T = retrofit.create(service) private fun getTokenFromPrefs(): String? { // Replace this with real SharedPreferences or DataStore logic return "your_token_here" } }
Step 4: Define Your API Interface (ApiService.kt
)
interface ApiService { @GET("user/profile") suspend fun getUserProfile(): Response<UserProfile> }
Step 5: Use the API in Your ViewModel or Repository
val api = ApiClient.create(ApiService::class.java) viewModelScope.launch { val response = api.getUserProfile() if (response.isSuccessful) { val user = response.body() // Handle success } else { // Handle other error codes Log.e("API_ERROR", "Error: ${response.code()}") } }
This setup ensures you handle 401/403 errors in a centralized manner using interceptors. It also prepares your codebase for further enhancements like token refresh workflows or user logout.
For more best practices on secure API integration, check out Retrofit’s official documentation.