From ab00d049906971f7813bbef36733499a993bde16 Mon Sep 17 00:00:00 2001 From: Kez Date: Sat, 25 Jan 2025 14:52:57 +0900 Subject: [PATCH 1/6] =?UTF-8?q?fix[api]:=20api=20exception=20=EC=9B=90?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/auth/authenticator/HMHAuthenticator.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt index 4be20e40b..abe5e1bb0 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt @@ -14,6 +14,7 @@ import okhttp3.Authenticator import okhttp3.Request import okhttp3.Response import okhttp3.Route +import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -32,8 +33,8 @@ class HMHAuthenticator @Inject constructor( if (response.code == 401) { val refreshToken = dataStore.refreshToken - val newTokens = runCatching { - runBlocking { + val newTokens = runBlocking { + runCatching { api.refreshToken("Bearer $refreshToken") } }.onSuccess { @@ -41,7 +42,7 @@ class HMHAuthenticator @Inject constructor( dataStore.refreshToken = data.refreshToken.orEmpty() dataStore.accessToken = data.accessToken.orEmpty() }.onFailure { - Log.e("Authenticator", it.toString()) + Timber.tag("Authenticator").e(it.toString()) runBlocking { dataStore.clear() databaseManager.deleteAll() From ee5251d5b0a4790bbb68e2c3a4d19a1eea9071bd Mon Sep 17 00:00:00 2001 From: Kez Date: Sat, 25 Jan 2025 14:54:06 +0900 Subject: [PATCH 2/6] test --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 5ae414012..7981973a9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ ![Alt](https://repobeats.axiom.co/api/embed/d2c401ae723c367a03ed9fb81ea6e6e7cfbee2ea.svg "Repobeats analytics image") -

Tech Stack

- [Android App Architecture](https://developer.android.com/topic/architecture) From 514e741a0405b21526615bed738b677ff3c563f2 Mon Sep 17 00:00:00 2001 From: Kez Date: Sat, 25 Jan 2025 14:56:41 +0900 Subject: [PATCH 3/6] test --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7981973a9..5ae414012 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ ![Alt](https://repobeats.axiom.co/api/embed/d2c401ae723c367a03ed9fb81ea6e6e7cfbee2ea.svg "Repobeats analytics image") +

Tech Stack

- [Android App Architecture](https://developer.android.com/topic/architecture) From 5e20b17b21001ca0775701bb39d2bcda43ffd1e9 Mon Sep 17 00:00:00 2001 From: Kez Date: Sat, 25 Jan 2025 14:57:52 +0900 Subject: [PATCH 4/6] test --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 5ae414012..7981973a9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ ![Alt](https://repobeats.axiom.co/api/embed/d2c401ae723c367a03ed9fb81ea6e6e7cfbee2ea.svg "Repobeats analytics image") -

Tech Stack

- [Android App Architecture](https://developer.android.com/topic/architecture) From 778f5330e89056c63ee381072101b45a2bec0f2c Mon Sep 17 00:00:00 2001 From: Kez Date: Sat, 25 Jan 2025 15:06:00 +0900 Subject: [PATCH 5/6] test --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7981973a9..4e62d1a75 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@
+ ![Alt](https://repobeats.axiom.co/api/embed/d2c401ae723c367a03ed9fb81ea6e6e7cfbee2ea.svg "Repobeats analytics image")

Tech Stack

From 349bded67765c24a9a9c5c29239e0fb8a8da891f Mon Sep 17 00:00:00 2001 From: Kez Date: Sat, 25 Jan 2025 16:34:31 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix[api]:=20api=20exception=20=EB=B0=A9?= =?UTF-8?q?=EC=A7=80=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/authenticator/HMHAuthenticator.kt | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt index abe5e1bb0..9808392db 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/auth/authenticator/HMHAuthenticator.kt @@ -1,7 +1,6 @@ package com.hmh.hamyeonham.core.network.auth.authenticator import android.content.Context -import android.util.Log import com.hmh.hamyeonham.common.navigation.NavigationProvider import com.hmh.hamyeonham.core.database.manger.DatabaseManager import com.hmh.hamyeonham.core.network.auth.api.RefreshService @@ -10,6 +9,8 @@ import com.jakewharton.processphoenix.ProcessPhoenix import com.kakao.sdk.user.UserApiClient import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import okhttp3.Authenticator import okhttp3.Request import okhttp3.Response @@ -26,37 +27,50 @@ class HMHAuthenticator @Inject constructor( private val databaseManager: DatabaseManager, private val navigationProvider: NavigationProvider, ) : Authenticator { + private val mutex = Mutex() + override fun authenticate(route: Route?, response: Response): Request? { - if (response.request.header("Authorization") == null) { + val originalRequest = response.request + if (originalRequest.header("Authorization") == null) { return null } + // 401 상태 처리 if (response.code == 401) { - val refreshToken = dataStore.refreshToken - val newTokens = runBlocking { - runCatching { - api.refreshToken("Bearer $refreshToken") - } - }.onSuccess { - val data = it.data - dataStore.refreshToken = data.refreshToken.orEmpty() - dataStore.accessToken = data.accessToken.orEmpty() - }.onFailure { - Timber.tag("Authenticator").e(it.toString()) - runBlocking { - dataStore.clear() - databaseManager.deleteAll() - UserApiClient.instance.logout { error -> - Log.e("Authenticator", error.toString()) - ProcessPhoenix.triggerRebirth(context, navigationProvider.toLogin()) + return runBlocking { + mutex.withLock { + try { + // 토큰 갱신 호출 + val refreshToken = dataStore.refreshToken + val newTokens = api.refreshToken("Bearer $refreshToken").data + + // 토큰 저장 + dataStore.accessToken = newTokens.accessToken.orEmpty() + dataStore.refreshToken = newTokens.refreshToken.orEmpty() + + // 새로운 요청 반환 + originalRequest.newBuilder() + .header("Authorization", "Bearer ${newTokens.accessToken}") + .build() + } catch (e: Exception) { + Timber.tag("Authenticator").e("Token refresh failed: ${e.message}") + handleLogout() + null } } - }.getOrThrow() - - return response.request.newBuilder() - .header("Authorization", "Bearer ${newTokens.data.accessToken}") - .build() + } } return null } -} + + private fun handleLogout() { + runBlocking { + dataStore.clear() + databaseManager.deleteAll() + UserApiClient.instance.logout { error -> + Timber.tag("Authenticator").e("Logout error: $error") + ProcessPhoenix.triggerRebirth(context, navigationProvider.toLogin()) + } + } + } +} \ No newline at end of file