From 55132e0c57ecf352b9c64ccbe51d240ad10c5238 Mon Sep 17 00:00:00 2001 From: Hafiz Date: Wed, 2 Jul 2025 13:29:27 -0500 Subject: [PATCH] Handle specific 401 errors by logging out the user Adds logic to check the error message from the API response when a 401 error is received. If the error indicates invalid credentials or missing authentication headers, the user is automatically logged out. --- .../data/implementation/ApiClientImpl.kt | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt index 93f11d03e..a6ca8de8c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt @@ -56,6 +56,7 @@ import okhttp3.Cache import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.logging.HttpLoggingInterceptor +import org.json.JSONObject import retrofit2.Converter import retrofit2.HttpException import retrofit2.Retrofit @@ -158,12 +159,33 @@ class ApiClientImpl( when (response.code) { 401 -> { val path = response.request.url.encodedPath - if (!path.contains("user/auth/update-password")) { - // token has been revoked/rotated elsewhere - HabiticaBaseApplication.logout(context) + if (!path.contains("/user/auth/update-password")) { + val bodyStr = try { + response.peekBody(1024).string() + } catch (_: Exception) { + "" + } + + val (errField, msgField) = try { + val obj = JSONObject(bodyStr) + obj.optString("error", "") to obj.optString("message", "") + } catch (_: Exception) { + "" to "" + } + + val shouldLogout = errField.equals("missingAuthHeaders", ignoreCase = true) + || errField.equals("invalidCredentials", ignoreCase = true) + || msgField.contains("invalidCredentials", ignoreCase = true) + || msgField.contains("Missing authentication headers", ignoreCase = true) + || msgField.contains("There is no account that uses those credentials", ignoreCase = true) + + if (shouldLogout) { + HabiticaBaseApplication.logout(context) + } } return@addNetworkInterceptor response } + 404 -> { // The server is returning a 404 error, which means the requested resource was not found. // In this case - we want to actually cache the response, and handle it in the app