← Back to docs
banner

Passkeys Playground

This is a playground for the webauthn wrapper library. Nothing here is sent to any server, everything runs locally.

Registration

A server-side randomly generated nonce, base64url encoded.
A username, email or other identifier
Which device to use as authenticator.
Whether a biometric/PIN check is required or not. This filters out security keys not having this capability.
A "discoverable" credential can be selected using `authenticate(...)` without providing credential IDs. Instead, a native pop-up will appear for user selection. This may have an impact on the "passkeys" user experience and syncing behavior of the key.
Number of milliseconds the user has to respond to the biometric/PIN check.

If enabled, the device attestation and clientData will be provided as base64 encoded binary data. Note that this may impact the authenticator information available or the UX depending on the platform.

Register device

Browser-side registration code:

await client.register({{registration.options}})

Will result in the following JSON to be sent to the server.

{{registration.json ?? '...'}}

Server-side verification code:

await server.verifyRegistration(registration, {challenge: "{{registration.options.challenge}}", origin: "{{origin}}"})

Resulting into:

{{registration.result ?? '...'}}

At this point, you should store the `credential` and associate it with the user account. You will need it later to verify authentication attempts.

Authentication

A server-side randomly generated nonce, base64url encoded.
Which devices to use as authenticator. Browser support varies.
Number of milliseconds the user has to respond to the biometric/PIN check.
Whether a biometric/PIN check is required or not. This filters out security keys not having this capability.
Here, you can place a list of allowed credentials. This can be used to skip the credentials selection process if the credntial IDs are known.
Login

Browser-side authentication code:

webauthn.authenticate({{authentication.options}})

Will result in the following JSON to be sent to the server.

{{authentication.json ?? '...'}}

Server-side code to verify the authentication:

const credentialKey = {
    id: "{{registration?.result?.credential?.id ?? '...'}}",
    publicKey: "{{registration?.result?.credential?.publicKey ?? '...'}}",
    algorithm: "{{registration?.result?.credential?.algorithm ?? '...'}}"
}

const expected = {
    challenge: "{{authentication?.options.challenge ?? '...'}}",
    origin: "{{origin}}",
    userVerified: {{authentication?.options?.userVerification === 'required'}},
    counter: -1
}

const verified = await server.verifyAuthentication(res, credentialKey, expected)
                

⚠️ In this demo, verification will only work if the same passkey as the one previoulsy registered is used. Information is not persisted.

Resulting into:

{{authentication.result ?? '...'}}

Signature validation

This part is mainly for debugging purposes or validation.


The algorithm used for the public key created during registration.
The public key created during registration.

{{parseAuthData(verification.authenticatorData)}}
{{parseClientData(verification.clientData)}}

signature = sign(algorithm, publicKey, authenticatorData + sha256(clientData))

Verify
Signature is {{verification.isValid ? 'valid' : 'invalid'}}