Skip to content

Commit 9aaade0

Browse files
authored
Added new error type to CredentialsManagerException class (#821)
1 parent b372f4b commit 9aaade0

File tree

5 files changed

+190
-0
lines changed

5 files changed

+190
-0
lines changed

auth0/src/main/java/com/auth0/android/authentication/storage/CredentialsManager.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.auth0.android.authentication.storage
22

33
import android.text.TextUtils
4+
import android.util.Log
45
import androidx.annotation.VisibleForTesting
56
import com.auth0.android.authentication.AuthenticationAPIClient
67
import com.auth0.android.authentication.AuthenticationException
@@ -110,6 +111,17 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting
110111
error
111112
)
112113
)
114+
} catch (exception: RuntimeException) {
115+
Log.e(
116+
TAG,
117+
"Caught unexpected exceptions while fetching sso token ${exception.stackTraceToString()}"
118+
)
119+
callback.onFailure(
120+
CredentialsManagerException(
121+
CredentialsManagerException.Code.UNKNOWN_ERROR,
122+
exception
123+
)
124+
)
113125
}
114126
}
115127
}
@@ -442,6 +454,20 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting
442454
exception, error
443455
)
444456
)
457+
} catch (exception: RuntimeException) {
458+
/**
459+
* Catching any unexpected runtime errors in the token renewal flow
460+
*/
461+
Log.e(
462+
TAG,
463+
"Caught unexpected exceptions for token renewal ${exception.stackTraceToString()}"
464+
)
465+
callback.onFailure(
466+
CredentialsManagerException(
467+
CredentialsManagerException.Code.UNKNOWN_ERROR,
468+
exception
469+
)
470+
)
445471
}
446472
}
447473
}
@@ -527,5 +553,6 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting
527553
// This is no longer used as we get the credentials expiry from the access token only,
528554
// but we still store it so users can rollback to versions where it is required.
529555
private const val LEGACY_KEY_CACHE_EXPIRES_AT = "com.auth0.cache_expires_at"
556+
private val TAG = CredentialsManager::class.java.simpleName
530557
}
531558
}

auth0/src/main/java/com/auth0/android/authentication/storage/CredentialsManagerException.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class CredentialsManagerException :
4646
NO_NETWORK,
4747
API_ERROR,
4848
SSO_EXCHANGE_FAILED,
49+
UNKNOWN_ERROR
4950
}
5051

5152
private var code: Code?
@@ -146,6 +147,8 @@ public class CredentialsManagerException :
146147
public val SSO_EXCHANGE_FAILED: CredentialsManagerException =
147148
CredentialsManagerException(Code.SSO_EXCHANGE_FAILED)
148149

150+
public val UNKNOWN_ERROR: CredentialsManagerException = CredentialsManagerException(Code.UNKNOWN_ERROR)
151+
149152

150153
private fun getMessage(code: Code): String {
151154
return when (code) {
@@ -191,6 +194,7 @@ public class CredentialsManagerException :
191194
Code.NO_NETWORK -> "Failed to execute the network request."
192195
Code.API_ERROR -> "An error occurred while processing the request."
193196
Code.SSO_EXCHANGE_FAILED ->"The exchange of the refresh token for SSO credentials failed."
197+
Code.UNKNOWN_ERROR -> "An unknown error has occurred while fetching the token. Please check the error cause for more details."
194198
}
195199
}
196200
}

auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,17 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
192192
CredentialsManagerException.Code.STORE_FAILED, error
193193
)
194194
callback.onFailure(exception)
195+
} catch (exception: RuntimeException) {
196+
Log.e(
197+
TAG,
198+
"Caught unexpected exceptions while fetching sso token ${exception.stackTraceToString()}"
199+
)
200+
callback.onFailure(
201+
CredentialsManagerException(
202+
CredentialsManagerException.Code.UNKNOWN_ERROR,
203+
exception
204+
)
205+
)
195206
}
196207
}
197208
}
@@ -680,6 +691,21 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
680691
)
681692
)
682693
return@execute
694+
} catch (exception: RuntimeException) {
695+
/**
696+
* Catching any unexpected runtime errors in the token renewal flow
697+
*/
698+
Log.e(
699+
TAG,
700+
"Caught unexpected exceptions for token renewal ${exception.stackTraceToString()}"
701+
)
702+
callback.onFailure(
703+
CredentialsManagerException(
704+
CredentialsManagerException.Code.UNKNOWN_ERROR,
705+
exception
706+
)
707+
)
708+
return@execute
683709
}
684710

685711
try {

auth0/src/test/java/com/auth0/android/authentication/storage/CredentialsManagerTest.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,31 @@ public class CredentialsManagerTest {
328328
)
329329
}
330330

331+
@Test
332+
public fun shouldFailOnGetNewSSOCredentialsWhenUnexpectedErrorOccurs() {
333+
Mockito.`when`(storage.retrieveString("com.auth0.refresh_token")).thenReturn("refreshToken")
334+
Mockito.`when`(
335+
client.ssoExchange("refreshToken")
336+
).thenReturn(SSOCredentialsRequest)
337+
//Trigger failure
338+
val runtimeException = RuntimeException(
339+
"unexpected_error"
340+
)
341+
Mockito.`when`(SSOCredentialsRequest.execute()).thenThrow(runtimeException)
342+
manager.getSsoCredentials(ssoCallback)
343+
verify(ssoCallback).onFailure(
344+
exceptionCaptor.capture()
345+
)
346+
val exception = exceptionCaptor.firstValue
347+
MatcherAssert.assertThat(exception, Is.`is`(Matchers.notNullValue()))
348+
MatcherAssert.assertThat(exception, Is.`is`(CredentialsManagerException.UNKNOWN_ERROR))
349+
MatcherAssert.assertThat(exception.cause, Is.`is`(runtimeException))
350+
MatcherAssert.assertThat(
351+
exception.message,
352+
Is.`is`("An unknown error has occurred while fetching the token. Please check the error cause for more details.")
353+
)
354+
}
355+
331356
@Test
332357
@ExperimentalCoroutinesApi
333358
public fun shouldFailOnAwaitSSOCredentialsWhenNoRefreshTokenWasSaved(): Unit = runTest {
@@ -1122,6 +1147,46 @@ public class CredentialsManagerTest {
11221147
)
11231148
}
11241149

1150+
@Test
1151+
public fun shouldGetAndFailToRenewExpiredCredentialsWhenAnyUnexpectedErrorOccurs() {
1152+
Mockito.`when`(storage.retrieveString("com.auth0.id_token")).thenReturn("idToken")
1153+
Mockito.`when`(storage.retrieveString("com.auth0.access_token")).thenReturn("accessToken")
1154+
Mockito.`when`(storage.retrieveString("com.auth0.refresh_token")).thenReturn("refreshToken")
1155+
Mockito.`when`(storage.retrieveString("com.auth0.token_type")).thenReturn("type")
1156+
val expirationTime = CredentialsMock.CURRENT_TIME_MS //Same as current time --> expired
1157+
Mockito.`when`(storage.retrieveLong("com.auth0.expires_at")).thenReturn(expirationTime)
1158+
Mockito.`when`(storage.retrieveLong("com.auth0.cache_expires_at"))
1159+
.thenReturn(expirationTime)
1160+
Mockito.`when`(storage.retrieveString("com.auth0.scope")).thenReturn("scope")
1161+
Mockito.`when`(
1162+
client.renewAuth("refreshToken")
1163+
).thenReturn(request)
1164+
//Trigger failure
1165+
val runtimeException = NullPointerException("Something went wrong")
1166+
Mockito.`when`(request.execute()).thenThrow(runtimeException)
1167+
manager.getCredentials(callback)
1168+
verify(storage, never())
1169+
.store(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())
1170+
verify(storage, never())
1171+
.store(ArgumentMatchers.anyString(), ArgumentMatchers.anyLong())
1172+
verify(storage, never())
1173+
.store(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())
1174+
verify(storage, never())
1175+
.store(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean())
1176+
verify(storage, never()).remove(ArgumentMatchers.anyString())
1177+
verify(callback).onFailure(
1178+
exceptionCaptor.capture()
1179+
)
1180+
val exception = exceptionCaptor.firstValue
1181+
MatcherAssert.assertThat(exception, Is.`is`(Matchers.notNullValue()))
1182+
MatcherAssert.assertThat(exception, Is.`is`(CredentialsManagerException.UNKNOWN_ERROR))
1183+
MatcherAssert.assertThat(exception.cause, Is.`is`(runtimeException))
1184+
MatcherAssert.assertThat(
1185+
exception.message,
1186+
Is.`is`("An unknown error has occurred while fetching the token. Please check the error cause for more details.")
1187+
)
1188+
}
1189+
11251190
@Test
11261191
public fun shouldClearCredentials() {
11271192
manager.clearCredentials()

auth0/src/test/java/com/auth0/android/authentication/storage/SecureCredentialsManagerTest.kt

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,37 @@ public class SecureCredentialsManagerTest {
378378
)
379379
}
380380

381+
@Test
382+
public fun shouldFailWhenUnexpectedErrorOccursOnGetSSOCredentials() {
383+
val expiresAt = Date(CredentialsMock.ONE_HOUR_AHEAD_MS)
384+
Mockito.`when`(client.ssoExchange("refreshToken"))
385+
.thenReturn(SSOCredentialsRequest)
386+
insertTestCredentials(
387+
hasIdToken = true,
388+
hasAccessToken = true,
389+
hasRefreshToken = true,
390+
willExpireAt = expiresAt,
391+
scope = "scope"
392+
)
393+
//Trigger failure
394+
val runtimeException = RuntimeException(
395+
"runtime exception"
396+
)
397+
Mockito.`when`(SSOCredentialsRequest.execute()).thenThrow(runtimeException)
398+
manager.getSsoCredentials(ssoCallback)
399+
verify(ssoCallback).onFailure(
400+
exceptionCaptor.capture()
401+
)
402+
val exception = exceptionCaptor.firstValue
403+
MatcherAssert.assertThat(exception, Is.`is`(Matchers.notNullValue()))
404+
MatcherAssert.assertThat(exception.cause, Is.`is`(runtimeException))
405+
MatcherAssert.assertThat(exception, Is.`is`(CredentialsManagerException.UNKNOWN_ERROR))
406+
MatcherAssert.assertThat(
407+
exception.message,
408+
Is.`is`("An unknown error has occurred while fetching the token. Please check the error cause for more details.")
409+
)
410+
}
411+
381412
/*
382413
* AWAIT SSO credentials test
383414
*/
@@ -1778,6 +1809,43 @@ public class SecureCredentialsManagerTest {
17781809
)
17791810
}
17801811

1812+
@Test
1813+
public fun shouldGetAndFailToRenewExpiredCredentialsWhenAnyUnexpectedErrorOccurs() {
1814+
Mockito.`when`(localAuthenticationManager.authenticate()).then {
1815+
localAuthenticationManager.resultCallback.onSuccess(true)
1816+
}
1817+
val expiresAt = Date(CredentialsMock.CURRENT_TIME_MS)
1818+
insertTestCredentials(false, true, true, expiresAt, "scope")
1819+
Mockito.`when`(
1820+
client.renewAuth("refreshToken")
1821+
).thenReturn(request)
1822+
//Trigger failure
1823+
val runtimeError =
1824+
RuntimeException("Something went wrong")
1825+
Mockito.`when`(request.execute()).thenThrow(runtimeError)
1826+
manager.getCredentials(callback)
1827+
verify(callback).onFailure(
1828+
exceptionCaptor.capture()
1829+
)
1830+
verify(storage, never())
1831+
.store(anyString(), anyLong())
1832+
verify(storage, never())
1833+
.store(anyString(), anyInt())
1834+
verify(storage, never())
1835+
.store(anyString(), anyString())
1836+
verify(storage, never())
1837+
.store(anyString(), anyBoolean())
1838+
verify(storage, never()).remove(anyString())
1839+
val exception = exceptionCaptor.firstValue
1840+
MatcherAssert.assertThat(exception, Is.`is`(Matchers.notNullValue()))
1841+
MatcherAssert.assertThat(exception, Is.`is`(CredentialsManagerException.UNKNOWN_ERROR))
1842+
MatcherAssert.assertThat(exception.cause, Is.`is`(runtimeError))
1843+
MatcherAssert.assertThat(
1844+
exception.message,
1845+
Is.`is`("An unknown error has occurred while fetching the token. Please check the error cause for more details.")
1846+
)
1847+
}
1848+
17811849
/**
17821850
* Testing that getCredentials execution from multiple threads via multiple instances of SecureCredentialsManager should trigger only one network request.
17831851
*/

0 commit comments

Comments
 (0)