Skip to content

Commit dac4dce

Browse files
committed
Saving the Dpop thumbprint
1 parent ec2c6ed commit dac4dce

3 files changed

Lines changed: 34 additions & 0 deletions

File tree

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import android.util.Log
44
import androidx.annotation.VisibleForTesting
55
import com.auth0.android.authentication.AuthenticationAPIClient
66
import com.auth0.android.callback.Callback
7+
import com.auth0.android.dpop.DPoPException
8+
import com.auth0.android.dpop.DPoPUtil
79
import com.auth0.android.result.APICredentials
810
import com.auth0.android.result.Credentials
911
import com.auth0.android.result.SSOCredentials
@@ -159,6 +161,29 @@ public abstract class BaseCredentialsManager internal constructor(
159161
internal val currentTimeInMillis: Long
160162
get() = _clock.getCurrentTimeMillis()
161163

164+
/**
165+
* Stores the DPoP key thumbprint if DPoP was used for this credential set.
166+
* Uses a dual strategy to store the thumbprint:
167+
* - credentials.type == "DPoP" when server confirms DPoP but client lacks useDPoP()
168+
* - isDPoPEnabled catches the case where client used DPoP, server returned token_type: "Bearer"
169+
*/
170+
protected fun saveDPoPThumbprint(credentials: Credentials) {
171+
val dpopUsed = credentials.type.equals("DPoP", ignoreCase = true)
172+
|| authenticationClient.isDPoPEnabled
173+
if (dpopUsed && DPoPUtil.hasKeyPair()) {
174+
try {
175+
val thumbprint = DPoPUtil.getPublicKeyJWK()
176+
if (thumbprint != null) {
177+
storage.store(KEY_DPOP_THUMBPRINT, thumbprint)
178+
}
179+
} catch (e: DPoPException) {
180+
Log.w(this::class.java.simpleName, "Failed to store DPoP key thumbprint", e)
181+
}
182+
} else {
183+
storage.remove(KEY_DPOP_THUMBPRINT)
184+
}
185+
}
186+
162187
/**
163188
* Checks if the stored scope is the same as the requested one.
164189
*

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting
7575
storage.store(KEY_EXPIRES_AT, credentials.expiresAt.time)
7676
storage.store(KEY_SCOPE, credentials.scope)
7777
storage.store(LEGACY_KEY_CACHE_EXPIRES_AT, credentials.expiresAt.time)
78+
saveDPoPThumbprint(credentials)
7879
}
7980

8081
/**
@@ -714,6 +715,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting
714715
storage.remove(KEY_EXPIRES_AT)
715716
storage.remove(KEY_SCOPE)
716717
storage.remove(LEGACY_KEY_CACHE_EXPIRES_AT)
718+
storage.remove(KEY_DPOP_THUMBPRINT)
717719
}
718720

719721
/**

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
189189
)
190190
storage.store(LEGACY_KEY_CACHE_EXPIRES_AT, credentials.expiresAt.time)
191191
storage.store(KEY_CAN_REFRESH, canRefresh)
192+
storage.store(KEY_TOKEN_TYPE, credentials.type)
193+
saveDPoPThumbprint(credentials)
192194
} catch (e: IncompatibleDeviceException) {
193195
throw CredentialsManagerException(
194196
CredentialsManagerException.Code.INCOMPATIBLE_DEVICE, e
@@ -735,6 +737,8 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
735737
storage.remove(KEY_EXPIRES_AT)
736738
storage.remove(LEGACY_KEY_CACHE_EXPIRES_AT)
737739
storage.remove(KEY_CAN_REFRESH)
740+
storage.remove(KEY_TOKEN_TYPE)
741+
storage.remove(KEY_DPOP_THUMBPRINT)
738742
clearBiometricSession()
739743
Log.d(TAG, "Credentials were just removed from the storage")
740744
}
@@ -1251,6 +1255,9 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
12511255
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
12521256
internal const val KEY_ALIAS = "com.auth0.key"
12531257

1258+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
1259+
internal const val KEY_TOKEN_TYPE = "com.auth0.token_type"
1260+
12541261
// Using NO_SESSION to represent "no session" (uninitialized state)
12551262
private const val NO_SESSION = -1L
12561263
}

0 commit comments

Comments
 (0)