androidauthenticationcredentialswebauthnpasskey

rpId validation failed in Passkeys PoC on Android using Jetpack Compose


I am working on a Passkeys Proof of Concept (PoC) for an Android app using Jetpack Compose. I've set up the required digital asset links (assetlinks.json) and domain verification for app-to-web authentication. Despite following the setup, I am encountering an error related to rpid validation failed when attempting to use passkeys.

I'm creating a passkey through the browser and then trying to use it in the native app.

Here’s what I’ve done:

Verified my domain using adb shell pm get-app-links my.package.example, which returns:

my.package.example:
  ID: 09699a58-4970-4dd8-8f30-323c5c792297
  Signatures: [CF:BF:CC:4C:AF:28:CF:82:35:F9:9D:D0:F5:C6:14:1A:AC:CF:E9:50:AA:12:25:80:E5:1D:BD:60:1E:04:21:53]
  Domain verification state:
    my.domain.com: 1024

Here’s my assetlinks.json:

[
    {
        "relation": [
            "delegate_permission/common.get_login_creds",
            "delegate_permission/common.handle_all_urls"
        ],
        "target": {
            "namespace": "android_app",
            "package_name": "my.package.example",
            "sha256_cert_fingerprints": [
                "CF:BF:CC:4C:AF:28:CF:82:35:F9:9D:D0:F5:C6:14:1A:AC:CF:E9:50:AA:12:25:80:E5:1D:BD:60:1E:04:21:53"
            ]
        }
    },
    {
        "relation": [
            "delegate_permission/common.handle_all_urls",
            "delegate_permission/common.get_login_creds"
        ],
        "target": {
            "namespace": "web",
            "site": "https://my.domain.com"
        }
    }
]

My AndroidManifest.xml includes an intent-filter with android:autoVerify="true":

<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" />
    <data android:host="my.domain.com" />
</intent-filter>

The domain is correctly included in the strings as well:

<string name="asset_statements" translatable="false">
  [{\"include\": \"https://my.domain.com/.well-known/assetlinks.json\"}]
</string>

I am passing the rpId in my JSON request:

val requestJson = JSONObject().apply {
    put("challenge", authorizationResponse.metadata.challenge)
    put("rpId", "my.domain.com")
    put("allowCredentials", JSONArray())
    put("timeout", 18000)
    put("userVerification", "required")
}

Despite all of this, I am still getting the following error:

rpId validation failed

and can't verify the domain using pm get-app-links my.package.example

Domain verification state: my.domain.com: 1024


Solution

  • You don't include your actual domain, so I can't check for you, but you can query the underlying service to check your domain's status:

    curl 'https://digitalassetlinks.googleapis.com/v1/assetlinks:check?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls&target.android_app.package_name=PACKAGE_NAME&target.android_app.certificate.sha256_fingerprint=APK_CERTIFICATE_FINGERPRINT'
    

    Be sure to replace PACKAGE_NAME and APK_CERTIFICATE_FINGERPRINT, of course. The latter should be in hex-with-colons format, as you have above.