On a iPhone, I have registered 2 different passkeys for 2 different users(Lets say user A and user B) for a domain example.com. Now at the time of authentication I am able to use Passkeys of user A to authenticate user B with authentication challenge fetched from server. This should not be allowed. As per documentation, I can see ASAuthorizationPlatformPublicKeyCredentialProvider.createCredentialAssertionRequest(challenge: challenge) only accepts challenge value and does not accept any user ID. How can I verify the user details/info while authenticating with Passkey.
Passkey registration and authentication on iPhone using native application
I could interpret this question in two different ways. I'm not sure which was intended, so I'll try to answer both.
- The app is expecting user B to sign in (e.g. B was the last account used on the device, but its cookies expired and needs to sign back in). The system passkey sheet comes up and I (the user) see passkeys for both A and B. I select A's passkey. Now, because the app was expecting user B to sign in, and I provided some valid assertion, I'm signed in as user B even though I used A's passkey.
If this is happening, it's a security error on the server side. The server should check the credentialID of the returned assertion and verify that it matches the user expected to be signed in, or (ideally) should just sign in the user that the credential ID belongs to (i.e. in this case, I should have been signed in to A's account even though the app expected me to sign in to B).
- The app is trying to perform an authorization for something specific to user B (e.g. a step-up re-auth protecting an important transaction). In this scenario, only B's passkeys are valid, and it wouldn't be valid to even show A's passkeys in the system sheet.
In this case, the app can improve this experience by setting ASAuthorizationPlatformPublicKeyCredentialAssertionRequest.allowedCredentials
. This lets the app specify an "allow list" of passkeys that can be used for this specific request. The app should pass an array of descriptors using all known credentialIDs for B's passkeys, which will ensure that only B's passkeys are shown in the system sheet or offered over the QR code flow (if the user decides to use that path).
I tried using ASAuthorizationPlatformPublicKeyCredentialAssertionRequest.allowedCredentials but did not succeed. Can you please provide the sample example how can I set ASAuthorizationPlatformPublicKeyCredentialAssertionRequest.allowedCredentials. From FIDO server, I am fetching authentication challenge as follows.
{ allowCredentials = ( { id = "MqOQAtJZsWgp_JqhwiGCCfOezOo"; transports = ( internal ); type = "public-key"; } ); challenge = "5_yN8CFmHDqYdNo5E2ijvWKUDY6ZnP_lm74DB1_KOco"; rpId = "example.com"; timeout = 120000; userVerification = required; }
Now how should I convert received allowCredentials object to [ASAuthorizationPlatformPublicKeyCredentialDescriptor(credentialID:Data]. There is no clear dcumentation on this.
One more sample of authentication challenge received from server
{ "challenge": "PKP-8Rpfhgvo6BM2zaN0KNjTixNNuKbtCzKiAjY2-no", "timeout": 120000, "rpId": "example.com", "allowCredentials": [ { "type": "public-key", "transports": [ "internal" ], "id": "MqOQAtJZsWgp_JqhwiGCCfOezOo" }, { "type": "public-key", "transports": [ "internal" ], "id": "tNprPiI0shGKljbYwI3niA" } ], "userVerification": "required" }