d8b934e2032a

fix: Preserve passkey verification requirement (v2.16.2)

- Prefer the authenticated BeginGet request JSON for passkey rows - Keep biometric user-verification semantics identical across row and Sign in paths - Retain final-request fallback for providers without an authenticated BeginGet payload - Verify 1,096 unit tests, lint, and signed release assembly

time
2026-09-06 19:00 UTC · 1 month ago
machine
koh2
parent
7eb176ce617a
3 files VERSION+1 −1app/src/main/java/com/peachpasswords/passkeys/PasskeyCredentialSelectionActivity.kt+10 −1app/src/test/java/com/peachpasswords/passkeys/CredentialProviderContractTest.kt+18 −0
VERSION+1 −1
@@ -1 +1 @@1-2.16.11+2.16.2

view file

app/src/main/java/com/peachpasswords/passkeys/PasskeyCredentialSelectionActivity.kt+10 −1
@@ -105,7 +105,10 @@105105         val option = providerRequest?.credentialOptions106106             ?.filterIsInstance<GetPublicKeyCredentialOption>()107107             ?.firstOrNull()108-        val requestJson = option?.requestJson ?: intent.getStringExtra(EXTRA_REQUEST_JSON)108+        val requestJson = selectionRequestJson(109+            frameworkJson = option?.requestJson,110+            authenticatedJson = intent.getStringExtra(EXTRA_REQUEST_JSON),111+        )109112         val clientDataHash = selectionClientDataHash(110113             frameworkHash = option?.clientDataHash,111114             authenticatedHash = intent.getByteArrayExtra(EXTRA_AUTHENTICATED_CLIENT_DATA_HASH),@@ -519,3 +522,9 @@519522     frameworkHash: ByteArray?,520523     authenticatedHash: ByteArray?,521524 ): ByteArray? = authenticatedHash ?: frameworkHash525+526+/** Keep UV/challenge semantics from the framework-authenticated BeginGet request. */527+internal fun selectionRequestJson(528+    frameworkJson: String?,529+    authenticatedJson: String?,530+): String? = authenticatedJson ?: frameworkJson

view file

app/src/test/java/com/peachpasswords/passkeys/CredentialProviderContractTest.kt+18 −0
@@ -54,6 +54,24 @@5454     }5555 5656     @Test57+    fun selectionKeepsAuthenticatedBeginJsonWhenSamsungDropsUvRequirement() {58+        val frameworkJson = """{"challenge":"final"}"""59+        val authenticatedJson =60+            """{"challenge":"begin","userVerification":"required"}"""61+62+        assertTrue(63+            selectionRequestJson(frameworkJson, authenticatedJson) == authenticatedJson,64+        )65+    }66+67+    @Test68+    fun selectionUsesFinalJsonOnlyWithoutAuthenticatedBeginJson() {69+        val frameworkJson = """{"challenge":"final"}"""70+71+        assertTrue(selectionRequestJson(frameworkJson, null) == frameworkJson)72+    }73+74+    @Test5775     fun providerOffersAnExplicitManualPasskeyChooser() {5876         val service = source("passkeys/PeachCredentialProviderService.kt")5977         val unlock = source("credentials/CredentialProviderUnlockActivity.kt")

view file