WebAuthn and FIDO2 (YubiKey)
You can enable WebAuthn in the Ory Identities (Kratos) to allow users to perform 2FA with 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:
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. - Depending on the framework you use, 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
- Sign in to the Ory Console and go to Two-Factor Authentication.
- In the WebAuthn section, use the switch to enable WebAuthn.
- Define the hostname of your login page. You must set this to your top-level domain.
- 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/https)
- host (
auth.example.com
) - port (
4455
)
If you are using the Ory Account Experience, leave these fields blank.
- Click Save to finish.
Ory CLI
Get the Ory Identities configuration from your project and save it to a file:
## List all available projects
ory list projects
## Get config
ory get identity-config <project-id> --format yaml > identity-config.yamlFind
webauthn
inselfservice/methods
, setenabled
totrue
, and define theid
(hostname) andorigin
of the login page users interact with:identity-config.yamlwebauthn:
config:
passwordless: false
rp:
display_name: MY_PROJECT_NAME
id: loginpage.com
# Set 'id' to the top-level domain.
origin: https://loginpage.auth.com:4455
# Set 'origin' to to the exact URL of the page that prompts user to use WebAuthn. You must include the scheme, host, and port.
enabled: trueinfoThe
display_name
is always set to the name of your project.Update the Ory Identities configuration using the file you worked with:
ory update identity-config <project-id> --file identity-config.yaml
Self-hosted instances
When working with self-hosted instances of Ory Identities (Ory Kratos), add the webauthn
method to selfservice/methods
in the
configuration file:
selfservice:
methods:
webauthn:
config:
passwordless: false
rp:
display_name: SAMPLE_NAME
# Set 'id' to the top-level domain.
id: loginpage.com
# Set 'origin' to the exact URL of the page that prompts the user to use WebAuthn. You must include the scheme, host, and port.
origin: https://loginpage.auth.com:4455
enabled: true
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.
In this example, the user's email address is the identifier:
This configuration is the default for The Ory Network.
{
"$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 tests used in Ory Identities (Kratos).
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==