mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 00:06:22 -06:00
PM-28053: Ensure any exception thrown during re-auth is an IO exception (#6175)
This commit is contained in:
parent
4623a4f079
commit
169b21cfdb
@ -81,6 +81,7 @@ internal class AuthTokenManager(
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val token = getAccessToken()
|
||||
?: throw IOException(IllegalStateException(MISSING_TOKEN_MESSAGE))
|
||||
@ -96,9 +97,12 @@ internal class AuthTokenManager(
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@Throws(IOException::class)
|
||||
private fun getAccessToken(): String? = authTokenProvider
|
||||
.getAuthTokenDataOrNull()
|
||||
?.let { getAccessToken(authTokenData = it).getOrThrow() }
|
||||
?.let { authTokenData ->
|
||||
getAccessToken(authTokenData = authTokenData).getOrElse { throw it.toIoException() }
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun getAccessToken(authTokenData: AuthTokenData): Result<String> {
|
||||
@ -117,3 +121,12 @@ internal class AuthTokenManager(
|
||||
|
||||
private fun Response.shouldSkipAuthentication(): Boolean = this.priorResponse != null
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to ensure the exception is an [IOException].
|
||||
*/
|
||||
private fun Throwable.toIoException(): IOException =
|
||||
when (this) {
|
||||
is IOException -> this
|
||||
else -> IOException(this)
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
@ -197,7 +198,7 @@ class AuthTokenManagerTest {
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `intercept should throw an exception when auth token is expired and refreshAccessTokenSynchronously returns an error`() {
|
||||
fun `intercept should throw an io exception when auth token is expired and refreshAccessTokenSynchronously returns an error`() {
|
||||
val errorMessage = "Fail!"
|
||||
authTokenManager.refreshTokenProvider = object : RefreshTokenProvider {
|
||||
override fun refreshAccessTokenSynchronously(
|
||||
@ -216,7 +217,31 @@ class AuthTokenManagerTest {
|
||||
chain = FakeInterceptorChain(request = request),
|
||||
)
|
||||
}
|
||||
assertEquals(errorMessage, throwable?.message)
|
||||
assertEquals(errorMessage, throwable.message)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `intercept should throw a http exception when auth token is expired and refreshAccessTokenSynchronously returns an error`() {
|
||||
val error = mockk<HttpException>()
|
||||
authTokenManager.refreshTokenProvider = object : RefreshTokenProvider {
|
||||
override fun refreshAccessTokenSynchronously(
|
||||
userId: String,
|
||||
): Result<String> = error.asFailure()
|
||||
}
|
||||
val authTokenData = AuthTokenData(
|
||||
userId = USER_ID,
|
||||
accessToken = ACCESS_TOKEN,
|
||||
expiresAtSec = FIXED_CLOCK.instant().epochSecond - 3600L,
|
||||
)
|
||||
every { mockAuthTokenProvider.getAuthTokenDataOrNull() } returns authTokenData
|
||||
|
||||
val throwable = assertThrows(IOException::class.java) {
|
||||
authTokenManager.intercept(
|
||||
chain = FakeInterceptorChain(request = request),
|
||||
)
|
||||
}
|
||||
assertEquals(throwable.cause, error)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user