@@ -209,25 +209,26 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
209209 * Stores the given [APICredentials] in the storage for the given audience.
210210 * @param apiCredentials the API Credentials to be stored
211211 * @param audience the audience for which the credentials are stored
212+ * @param scope the scope for which the credentials are stored
212213 */
213- override fun saveApiCredentials (apiCredentials : APICredentials , audience : String ) {
214+ override fun saveApiCredentials (
215+ apiCredentials : APICredentials ,
216+ audience : String ,
217+ scope : String?
218+ ) {
219+ val key = getAPICredentialsKey(audience, scope)
214220 val json = gson.toJson(apiCredentials)
215221 try {
216222 val encrypted = crypto.encrypt(json.toByteArray())
217223 val encryptedEncoded = Base64 .encodeToString(encrypted, Base64 .DEFAULT )
218- storage.store(audience , encryptedEncoded)
224+ storage.store(key , encryptedEncoded)
219225 } catch (e: IncompatibleDeviceException ) {
220226 throw CredentialsManagerException (
221227 CredentialsManagerException .Code .INCOMPATIBLE_DEVICE ,
222228 e
223229 )
224230 } catch (e: CryptoException ) {
225- /*
226- * If the keys were invalidated in the call above a good new pair is going to be available
227- * to use on the next call. We clear any existing credentials so #hasValidCredentials returns
228- * a true value. Retrying this operation will succeed.
229- */
230- clearApiCredentials(audience)
231+ clearApiCredentials(audience, scope)
231232 throw CredentialsManagerException (
232233 CredentialsManagerException .Code .CRYPTO_EXCEPTION ,
233234 e
@@ -331,12 +332,10 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
331332
332333 public override val userProfile: UserProfile ?
333334 get() {
334- val credentials: Credentials ? = getExistingCredentials()
335- // Handle null credentials gracefully
336- if (credentials == null ) {
337- return null
338- }
339- return credentials.user
335+ return runCatching {
336+ val credentials: Credentials = getExistingCredentials()
337+ return credentials.user
338+ }.getOrNull()
340339 }
341340
342341 /* *
@@ -765,10 +764,13 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
765764
766765 /* *
767766 * Removes the credentials for the given audience from the storage if present.
767+ * @param audience Audience for which the [APICredentials] are stored
768+ * @param scope Optional scope for which the [APICredentials] are stored. If the credentials were initially fetched/stored with scope,
769+ * it is recommended to pass scope also while clearing them.
768770 */
769- override fun clearApiCredentials (audience : String ) {
770- storage.remove (audience)
771- Log .d( TAG , " API Credentials for $audience were just removed from the storage " )
771+ override fun clearApiCredentials (audience : String , scope : String? ) {
772+ val key = getAPICredentialsKey (audience, scope )
773+ storage.remove(key )
772774 }
773775
774776 /* *
@@ -965,7 +967,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
965967 callback : Callback <APICredentials , CredentialsManagerException >
966968 ) {
967969 serialExecutor.execute {
968- val encryptedEncodedJson = storage.retrieveString(audience)
970+ val encryptedEncodedJson = storage.retrieveString(getAPICredentialsKey( audience, scope) )
969971 // Check if existing api credentials are present and valid
970972
971973 encryptedEncodedJson?.let { encryptedEncoded ->
@@ -981,8 +983,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
981983 )
982984 return @execute
983985 } catch (e: CryptoException ) {
984- // If keys were invalidated, existing credentials will not be recoverable.
985- clearApiCredentials(audience)
986+ clearApiCredentials(audience, scope)
986987 callback.onFailure(
987988 CredentialsManagerException (
988989 CredentialsManagerException .Code .CRYPTO_EXCEPTION ,
@@ -996,7 +997,10 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
996997
997998 val expiresAt = apiCredentials.expiresAt.time
998999 val willAccessTokenExpire = willExpire(expiresAt, minTtl.toLong())
999- val scopeChanged = hasScopeChanged(apiCredentials.scope, scope)
1000+ val scopeChanged = hasScopeChanged(
1001+ apiCredentials.scope, scope,
1002+ ignoreOpenid = scope?.contains(" openid" ) == false
1003+ )
10001004 val hasExpired = hasExpired(apiCredentials.expiresAt.time)
10011005 if (! hasExpired && ! willAccessTokenExpire && ! scopeChanged) {
10021006 callback.onSuccess(apiCredentials)
@@ -1051,7 +1055,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
10511055 idToken = newCredentials.idToken
10521056 )
10531057 )
1054- saveApiCredentials(newApiCredentials, audience)
1058+ saveApiCredentials(newApiCredentials, audience, scope )
10551059 callback.onSuccess(newApiCredentials)
10561060
10571061 } catch (error: AuthenticationException ) {
@@ -1200,6 +1204,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
12001204
12011205 val policy = localAuthenticationOptions?.policy ? : BiometricPolicy .Always
12021206 return when (policy) {
1207+
12031208 is BiometricPolicy .Session ,
12041209 is BiometricPolicy .AppLifecycle -> {
12051210 val timeoutMillis = when (policy) {
0 commit comments