Skip to content

Commit

Permalink
catch nullpointerexception when getting credentials during deserializ…
Browse files Browse the repository at this point in the history
…ation of json
  • Loading branch information
bennycao committed Dec 6, 2023
1 parent c17b87b commit 9b213f3
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import androidx.annotation.VisibleForTesting
import androidx.lifecycle.Lifecycle
import com.auth0.android.Auth0Exception
import com.auth0.android.authentication.AuthenticationAPIClient
import com.auth0.android.authentication.AuthenticationException
import com.auth0.android.callback.AuthenticationCallback
import com.auth0.android.callback.Callback
import com.auth0.android.request.internal.GsonProvider
import com.auth0.android.result.Credentials
Expand Down Expand Up @@ -146,7 +144,14 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
return false
}
if (resultCode == Activity.RESULT_OK) {
continueGetCredentials(scope, minTtl, emptyMap(), emptyMap(), forceRefresh, decryptCallback!!)
continueGetCredentials(
scope,
minTtl,
emptyMap(),
emptyMap(),
forceRefresh,
decryptCallback!!
)
} else {
decryptCallback!!.onFailure(CredentialsManagerException("The user didn't pass the authentication challenge."))
decryptCallback = null
Expand Down Expand Up @@ -547,7 +552,16 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
decryptCallback = null
return@execute
}
val bridgeCredentials = gson.fromJson(json, OptionalCredentials::class.java)

val bridgeCredentials: OptionalCredentials
try {
bridgeCredentials = gson.fromJson(json, OptionalCredentials::class.java)
} catch (ex: NullPointerException) {
callback.onFailure(CredentialsManagerException("Credentials could not be retrieved."))
decryptCallback = null
return@execute
}

/* OPTIONAL CREDENTIALS
* This bridge is required to prevent users from being logged out when
* migrating from Credentials with optional Access Token and ID token
Expand Down Expand Up @@ -641,8 +655,9 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
callback.onSuccess(freshCredentials)
} catch (error: CredentialsManagerException) {
val exception = CredentialsManagerException(
"An error occurred while saving the refreshed Credentials.", error)
if(error.cause is IncompatibleDeviceException || error.cause is CryptoException) {
"An error occurred while saving the refreshed Credentials.", error
)
if (error.cause is IncompatibleDeviceException || error.cause is CryptoException) {
exception.refreshedCredentials = freshCredentials
}
callback.onFailure(exception)
Expand All @@ -655,6 +670,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
private val TAG = SecureCredentialsManager::class.java.simpleName
private const val KEY_CREDENTIALS = "com.auth0.credentials"
private const val KEY_EXPIRES_AT = "com.auth0.credentials_access_token_expires_at"

// This is no longer used as we get the credentials expiry from the access token only,
// but we still store it so users can rollback to versions where it is required.
private const val LEGACY_KEY_CACHE_EXPIRES_AT = "com.auth0.credentials_expires_at"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,41 @@ public class SecureCredentialsManagerTest {
MatcherAssert.assertThat(retrievedCredentials.scope, Is.`is`("different scope"))
}

@Test
public fun shouldFailOnGetCredentialsWhenNullPointerExceptionIsThrown() {
verifyNoMoreInteractions(client)
val expiresAt = Date(CredentialsMock.ONE_HOUR_AHEAD_MS)
val storedJson = insertTestCredentials(
hasIdToken = true,
hasAccessToken = true,
hasRefreshToken = true,
willExpireAt = expiresAt,
scope = "scope"
)

Mockito.`when`(crypto.decrypt(storedJson.toByteArray()))
.thenReturn("".toByteArray())

manager.getCredentials(callback)
verify(callback).onFailure(
exceptionCaptor.capture()
)
val exception = exceptionCaptor.firstValue
MatcherAssert.assertThat(exception, Is.`is`(Matchers.notNullValue()))
MatcherAssert.assertThat(
exception, IsInstanceOf.instanceOf(
CredentialsManagerException::class.java
)
)
MatcherAssert.assertThat(
exception.message,
Is.`is`("Credentials could not be retrieved.")
)
verify(storage, never()).remove("com.auth0.credentials")
verify(storage, never()).remove("com.auth0.credentials_expires_at")
verify(storage, never()).remove("com.auth0.credentials_can_refresh")
}

@Test
public fun shouldFailOnSavingRefreshedCredentialsInGetCredentialsWhenIncompatibleDeviceExceptionIsThrown() {
val expiresAt = Date(CredentialsMock.ONE_HOUR_AHEAD_MS) // non expired credentials
Expand Down

0 comments on commit 9b213f3

Please sign in to comment.