Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ plugins {
}

val publishGroupId = "com.stytch.sdk"
val publishVersion = "0.64.0"
val publishVersion = "0.65.0"
val publishArtifactId = "sdk"

android {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,33 @@ public sealed class BiometricAvailability {
fun fromReason(reason: Int) =
Unavailable(
when (reason) {
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> {
Reason.BIOMETRIC_ERROR_NO_HARDWARE
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
}

BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> {
Reason.BIOMETRIC_ERROR_HW_UNAVAILABLE
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED ->
}

BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
Reason.BIOMETRIC_ERROR_NONE_ENROLLED
BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED ->
}

BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> {
Reason.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED ->
}

BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> {
Reason.BIOMETRIC_ERROR_UNSUPPORTED
BiometricManager.BIOMETRIC_STATUS_UNKNOWN ->
}

BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> {
Reason.BIOMETRIC_STATUS_UNKNOWN
else ->
}

else -> {
Reason.BIOMETRIC_STATUS_UNKNOWN
}
},
)
}
Expand All @@ -93,6 +106,12 @@ public sealed class BiometricAvailability {

@JacocoExcludeGenerated public data object RegistrationRevoked : BiometricAvailability()

/**
* Indicates that a cryptographic operation could not be performed because the user has not been
* authenticated recently enough. Authenticating the user will resolve this issue.
*/
@JacocoExcludeGenerated public data object UserAuthenticationRequired : BiometricAvailability()

/**
* Status indicating that biometrics are available, but no registrations have been made yet
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.stytch.sdk.consumer.biometrics

import android.os.Build
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.UserNotAuthenticatedException
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
Expand Down Expand Up @@ -31,6 +32,7 @@ import kotlinx.coroutines.future.asCompletableFuture
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.security.InvalidAlgorithmParameterException
import java.security.InvalidKeyException
import java.util.concurrent.CompletableFuture

internal const val LAST_USED_BIOMETRIC_REGISTRATION_ID = "last_used_biometric_registration_id"
Expand Down Expand Up @@ -78,7 +80,13 @@ internal class BiometricsImpl internal constructor(
var errorEncounteredWhenGeneratingKey = false
try {
biometricsProvider.ensureSecretKeyIsAvailable(allowedAuthenticators)
} catch (_: KeyPermanentlyInvalidatedException) {
} catch (_: UserNotAuthenticatedException) {
// Indicates that a cryptographic operation could not be performed because the user has not been
// authenticated recently enough. Authenticating the user will resolve this issue.
return BiometricAvailability.UserAuthenticationRequired
} catch (_: InvalidKeyException) {
// This covers all other instances of invalid keys, where a registration WAS available
// but the key is not valid, so we should revoke the registration and have them re-register
externalScope.launch(dispatchers.io) {
removeRegistration()
}
Expand All @@ -104,7 +112,10 @@ internal class BiometricsImpl internal constructor(
false -> BiometricAvailability.AvailableNoRegistrations
}
}
else -> BiometricAvailability.Unavailable.fromReason(result)

else -> {
BiometricAvailability.Unavailable.fromReason(result)
}
}
}

Expand All @@ -121,7 +132,10 @@ internal class BiometricsImpl internal constructor(
removeLocalRegistrationOnly()
true
}
else -> false

else -> {
false
}
}
}

Expand Down
Loading