Skip to main content

WebAuthn and FIDO2 (YubiKey)

WebAuthn uses the Web Authentication API of the browser, which allows servers to register and authenticate users using public-key cryptography.

There are two main categories of authenticators you can use with WebAuthn:

  • On-device authenticators: platform-based biometric authentication protocols, such as TouchID, FaceID, Windows Hello, or Android Biometric Authentication
  • External authenticators: NFC devices, USB keys, or Bluetooth Low Energy (BLE) devices, for example a YubiKey.

When accessing resources protected with the second-factor requirement, the browser presents the user with a prompt asking to confirm their identity with their configured authentication method, for example, by touching the fingerprint reader.

You can enable WebAuthn in the Ory Identities (Kratos) to allow users to perform 2FA with physical devices such as USB keys or OS-level biometric authentication protocols, such as TouchID.

When users trigger the WebAuthn process, the web browser displays a prompt:

https://console.ory.sh/

WebAuthn prompt in Google Chrome

The look of the prompt depends on the web browser. The screenshot shows a Google Chrome prompt.

Limitations

  • WebAuthn is a browser-only standard. It doesn't work with native mobile apps.
  • WebAuthn is limited to one domain and does not work in a local environment when using CNAME / Ory Proxy. WebAuthn uses an https://origin URL as part of the client-server challenge/response mechanism. This mechanism allows a single URL as the origin. To learn more, read this WebAuthn discussion and on GitHub.
  • Implementing WebAuthn in your own UI can be challenging. Check out the reference implementations to see how you can approach implementation for different app types (web app, SPA).

Configuration

Follow these steps to enable WebAuthn as the second authentication factor:

Ory Console

  1. Sign in to the Ory Console and go to Two-Factor Authentication.
  2. In the WebAuthn section, use the switch to enable WebAuthn.
  3. Define the hostname of your login page. You must set this to your top-level domain.
note

If you are using the Ory Account Experience, skip the 4. step

  1. Define the origin of your login page. Set it to the exact URL of the page that prompts the user to use WebAuthn. The relevant items are:

    • scheme (http or https)
    • host (auth.example.com)
    • port (4455)
  2. Click Save to finish.

https://console.ory.sh/

WebAuthn settings in Ory Console

Distinguish identities requesting WebAuthn

To help users distinguish which identity requests for WebAuthn authentication, add a webauthn object to the trait which represents the WebAuthn account name. This trait's value will show up in the WebAuthn prompt of the browser.

In this example, the user's email address is the identifier:

note

This configuration is the default for the Ory Network.

sample identity schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"traits": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"title": "Your E-Mail",
"minLength": 3,
"ory.sh/kratos": {
"credentials": {
// ...
"webauthn": {
"identifier": true
}
}
// ...
}
}
// ...
}
// ...
}
}
}

Writing E2E tests

When writing end-to-end (E2E) tests for WebAuthn implementation in your app, you can reference the Cypress E2E tests used in Ory Identities (Kratos).

tip

To learn more about the approach used in Cypress, read this GitHub issue.

Identity credentials

When the user enables WebAuthn, Ory adds the following entries to the credentials object of the associated identity:

credentials:
password:
id: webauthn
identifiers:
- alice@example.org
config:
credentials:
- display_name: my-key
added_at: "2022-03-06T09:45:18Z"
# If 'true', WebAuthn is used for paswordless flows.
is_passwordless: false
# WebAuth2-specific values.
id: P/psShpG+SOCxBqslynuxMors6oexs7RS09bSA/F9EI=
public_key: pQECAyYgASFYIJ0RRsaHJ2IQ6Eh11BPpHkdOl2DkICXg3rJVxSHQAsklIlgga0Tt2PqLlg/baAl20Y64JCllE71jDG+XzHfN6FT/S9I=
attestation_type: none
authenticator:
aaguid: AAAAAAAAAAAAAAAAAAAAAA==
sign_count: 1
clone_warning: false
# The user handle will be used in the exchange with the FIDO2 device
# to ensure that the user handle from the key and from Ory match.
user_handle: NDVP4/1nTj2CTFaItp/zXg==