Skip to content

Commit 1c32230

Browse files
feat: Enhance biometric session management and update examples
1 parent e619593 commit 1c32230

File tree

4 files changed

+27
-50
lines changed

4 files changed

+27
-50
lines changed

EXAMPLES.md

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,33 +1464,22 @@ BiometricPolicy controls when biometric authentication is required when accessin
14641464
// Always require biometric authentication (default)
14651465
val alwaysPolicy = LocalAuthenticationOptions.Builder()
14661466
.setTitle("Authenticate")
1467-
.setDescription("Accessing Credentials")
14681467
.setAuthenticationLevel(AuthenticationLevel.STRONG)
14691468
.setPolicy(BiometricPolicy.Always)
14701469
.build()
14711470

14721471
// Require authentication only once per 5-minute session
14731472
val sessionPolicy = LocalAuthenticationOptions.Builder()
14741473
.setTitle("Authenticate")
1475-
.setDescription("Accessing Credentials")
14761474
.setAuthenticationLevel(AuthenticationLevel.STRONG)
14771475
.setPolicy(BiometricPolicy.Session(300)) // 5 minutes
14781476
.build()
14791477

1480-
// Require authentication once per app lifecycle (1 hour timeout)
1478+
// Require authentication once per app lifecycle (1 hour default)
14811479
val appLifecyclePolicy = LocalAuthenticationOptions.Builder()
14821480
.setTitle("Authenticate")
1483-
.setDescription("Accessing Credentials")
14841481
.setAuthenticationLevel(AuthenticationLevel.STRONG)
1485-
.setPolicy(BiometricPolicy.AppLifecycle()) // Uses default 1 hour timeout
1486-
.build()
1487-
1488-
// Custom app lifecycle timeout (2 hours)
1489-
val customAppLifecyclePolicy = LocalAuthenticationOptions.Builder()
1490-
.setTitle("Authenticate")
1491-
.setDescription("Accessing Credentials")
1492-
.setAuthenticationLevel(AuthenticationLevel.STRONG)
1493-
.setPolicy(BiometricPolicy.AppLifecycle(7200)) // 2 hours
1482+
.setPolicy(BiometricPolicy.AppLifecycle()) // Default: 3600 seconds (1 hour)
14941483
.build()
14951484
```
14961485

@@ -1501,29 +1490,38 @@ val customAppLifecyclePolicy = LocalAuthenticationOptions.Builder()
15011490
// Always require biometric authentication (default)
15021491
LocalAuthenticationOptions alwaysPolicy = new LocalAuthenticationOptions.Builder()
15031492
.setTitle("Authenticate")
1504-
.setDescription("Accessing Credentials")
15051493
.setAuthenticationLevel(AuthenticationLevel.STRONG)
15061494
.setPolicy(BiometricPolicy.Always.INSTANCE)
15071495
.build();
15081496

15091497
// Require authentication only once per 5-minute session
15101498
LocalAuthenticationOptions sessionPolicy = new LocalAuthenticationOptions.Builder()
15111499
.setTitle("Authenticate")
1512-
.setDescription("Accessing Credentials")
15131500
.setAuthenticationLevel(AuthenticationLevel.STRONG)
15141501
.setPolicy(new BiometricPolicy.Session(300)) // 5 minutes
15151502
.build();
15161503

1517-
// Require authentication once per app lifecycle (1 hour timeout)
1504+
// Require authentication once per app lifecycle (default 1 hour)
15181505
LocalAuthenticationOptions appLifecyclePolicy = new LocalAuthenticationOptions.Builder()
15191506
.setTitle("Authenticate")
1520-
.setDescription("Accessing Credentials")
15211507
.setAuthenticationLevel(AuthenticationLevel.STRONG)
1522-
.setPolicy(new BiometricPolicy.AppLifecycle()) // Uses default 1 hour timeout
1508+
.setPolicy(new BiometricPolicy.AppLifecycle()) // Default: 3600 seconds
15231509
.build();
15241510
```
15251511
</details>
15261512

1513+
**Managing Biometric Sessions**:
1514+
1515+
You can manually clear the biometric session to force re-authentication on the next credential access:
1516+
1517+
```kotlin
1518+
// Clear the biometric session
1519+
secureCredentialsManager.clearBiometricSession()
1520+
1521+
// Check if the current session is valid
1522+
val isValid = secureCredentialsManager.isBiometricSessionValid()
1523+
```
1524+
15271525

15281526
### Other Credentials
15291527

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ public sealed class BiometricPolicy {
2020
* The session is invalidated by calling clearBiometricSession() or after the default timeout.
2121
* @param timeoutInSeconds The duration for which the session remains valid. Defaults to 3600 seconds (1 hour).
2222
*/
23-
public data class AppLifecycle(val timeoutInSeconds: Int = 3600) : BiometricPolicy() // Default 1 hour
23+
public data class AppLifecycle @JvmOverloads constructor(val timeoutInSeconds: Int = 3600) : BiometricPolicy() // Default 1 hour
2424
}

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
4949
) : BaseCredentialsManager(apiClient, storage, jwtDecoder) {
5050
private val gson: Gson = GsonProvider.gson
5151

52+
// Biometric session management
53+
private val lastBiometricAuthTime = AtomicLong(NO_SESSION)
54+
5255
/**
5356
* Creates a new SecureCredentialsManager to handle Credentials
5457
*
@@ -1136,13 +1139,14 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
11361139
val lastAuth = lastBiometricAuthTime.get()
11371140
if (lastAuth == NO_SESSION) return false // No session exists
11381141

1139-
return when (biometricPolicy) {
1140-
is BiometricPolicy.Session -> {
1141-
val timeoutMillis = biometricPolicy.timeoutInSeconds * 1000L
1142-
System.currentTimeMillis() - lastAuth < timeoutMillis
1143-
}
1142+
return when (val policy = biometricPolicy) {
1143+
is BiometricPolicy.Session,
11441144
is BiometricPolicy.AppLifecycle -> {
1145-
val timeoutMillis = biometricPolicy.timeoutInSeconds * 1000L
1145+
val timeoutMillis = when (policy) {
1146+
is BiometricPolicy.Session -> policy.timeoutInSeconds
1147+
is BiometricPolicy.AppLifecycle -> policy.timeoutInSeconds
1148+
else -> return false
1149+
} * 1000L
11461150
System.currentTimeMillis() - lastAuth < timeoutMillis
11471151
}
11481152
is BiometricPolicy.Always -> false
@@ -1183,9 +1187,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT
11831187
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
11841188
internal const val KEY_ALIAS = "com.auth0.key"
11851189

1186-
// Biometric session management
11871190
// Using NO_SESSION to represent "no session" (uninitialized state)
11881191
private const val NO_SESSION = -1L
1189-
private val lastBiometricAuthTime = AtomicLong(NO_SESSION)
11901192
}
11911193
}

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

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -73,29 +73,6 @@ public class SecureCredentialsManagerBiometricPolicyTest {
7373
assert(policy1 == policy2) // Equal
7474
}
7575

76-
@Test
77-
public fun `BiometricPolicy Session should be data class with timeout parameter`() {
78-
val policy1 = BiometricPolicy.Session(300)
79-
val policy2 = BiometricPolicy.Session(300)
80-
val policy3 = BiometricPolicy.Session(600)
81-
82-
assert(policy1 == policy2) // Same timeout, should be equal
83-
assert(policy1 != policy3) // Different timeout, should not be equal
84-
assert(policy1.timeoutInSeconds == 300)
85-
}
86-
87-
@Test
88-
public fun `BiometricPolicy AppLifecycle should be data class with default timeout`() {
89-
val policy1 = BiometricPolicy.AppLifecycle()
90-
val policy2 = BiometricPolicy.AppLifecycle()
91-
val policy3 = BiometricPolicy.AppLifecycle(7200)
92-
93-
assert(policy1 == policy2) // Same default timeout, should be equal
94-
assert(policy1 != policy3) // Different timeout, should not be equal
95-
assert(policy1.timeoutInSeconds == 3600) // Default 1 hour
96-
assert(policy3.timeoutInSeconds == 7200) // Custom 2 hours
97-
}
98-
9976
@Test
10077
public fun `AppLifecycle policy should default to 1 hour timeout`() {
10178
val policy = BiometricPolicy.AppLifecycle()

0 commit comments

Comments
 (0)