I'm working on integrating WebAuthn into my web application and encountering an issue specifically with Windows Hello and the handling of allowCredentials. When I don't specify allowCredentialsin the publicKeyCredentialRequestOptions, I get a prompt allowing me to choose from available credentials, and upon selection, I'm then asked to enter the PIN for the selected credential. This flow works as expected.
However, my goal is to streamline the process by pre-selecting the credential using allowCredentials, thus skipping the credential selection step. When I do specify allowCredentialswith the correct credential ID, the expected PIN prompt does not appear. Instead, I'm only presented with two options: "iPhone, iPad, or Android device" and "Security Key".
Here's the code snippet for context:
const publicKeyCredentialRequestOptions = {
challenge: serverChallenge,
rpId: window.location.hostname,
userVerification: 'required',
allowCredentials: [
{
type: "public-key",
id: allowCredentials[0].id,
}
],
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions
});
The allowCredentials[0].id is verified to be correct. The issue is that specifying allowCredentials emphasized textseems to bypass the PIN entry step for Windows Hello, directly prompting for an alternate authentication method instead.
Has anyone faced a similar issue or have insights on why the PIN prompt is bypassed in this case? Any advice on how to ensure the PIN prompt appears when allowCredentials is used would be greatly appreciated.
Thank you for your assistance!
I am assuming a bit here but I would guess that the ID you send in is actually not in the format expected. The
allowCredentialexpects a PublicKeyCredentialDescriptor which eexpects that the ID is sent in as aBufferSource. However the PublicKeyCredential response object from the creation is not of the same type. For thePublicKeyCredentialtheidis abase64urlencoded string of the ID and not an actualBufferSource.This would result in WebAuthn asking all platform authenticators first, and Windows Hello is a Platform Authenticcator, and they would all respond that they don't know said credential which would prompt you to use cross-platform authenticators, or as you refer to it as alternate authenticators.
As I said, I am assuming a bit, but I assume the
allowCredentials[0].idis a reference to aPublicKeyCredentialin which case swapping toallowCredentials[0].rawIdwould probably fix the issue.If it is not a
PublicKeyCredentialyou'd need to convert your id to a BufferSource. As said earlier I assume it is a base64 encoded string so something likenew Uint8Array(Buffer.from(allowCredentials[0].id, 'base64'))might solve it. But this all depends a bit that my assumptions are correct.