Misconfigurations in WebAuthn server settings can lead to UX problems and disrupt existing passkeys. This guide helps developers to set up WebAuthn servers.
Vincent
Created: September 28, 2023
Updated: October 1, 2024
Our mission is to make the Internet a safer place, and the new login standard passkeys provides a superior solution to achieve that. That's why we want to help you understand passkeys and its characteristics better.
4. What are Resident Keys and Non-Resident Keys?
5. Conditional UI ("Passkey Autofill")
6. Client to Authenticator Protocol (CTAP)
7.1 WebAuthn Server Option Authenticator Attachment
7.2 WebAuthn Server Option Resident Key
7.3 WebAuthn Server Option User Verification
7.4 Common Patterns of WebAuthn Server Options
7.4.1 Passwordless Login with Passkeys via Face ID / Touch ID
7.4.1 Passwordless Login with Security Keys (e.g. YubiKeys)
8. Potential Challenges and Solutions
8.1 Challenge 1: Storage Limitations of Security Keys (e.g. YubiKeys)
8.2 Challenge 2: Inconsistent Behavior Across Authenticators
8.3 Challenge 3: User Experience Concerns
9. Best Practices for Developers and Product Managers
Passkeys and the underlying WebAuthn protocol are revolutionizing the authentication landscape. However, setting up a WebAuthn server the proper way can be a tricky endeavor. Misconfigurations can not only introduce vulnerabilities but also break existing passkeys if you need to change them later. The following blog post should help you better understand the often complex WebAuthn specifications and give you the advice what settings are best for your use case.
WebAuthn operates with three primary entities:
Want to try passkeys yourself? Check our Passkeys Demo.
Try PasskeysIn the following, the high-level data flow during an authentication process (either login or sign-up) is described.
Ben Gould
Head of Engineering
I’ve built hundreds of integrations in my time, including quite a few with identity providers and I’ve never been so impressed with a developer experience as I have been with Corbado.
10,000+ devs trust Corbado & make the Internet safer with passkeys. Got questions? We’ve written 150+ blog posts on passkeys.
Join Passkeys CommunityThe above described high-level process flow describes WebAuthn sign-up and login processes. Passkeys are built on top of WebAuthn. Originally, the term passkeys was used as a more memorable and non-technical term than WebAuthn describing the same thing. Moreover, passkeys provide more features compared to standard WebAuthn, e.g. the possibility to sync passkeys via cloud accounts or password managers.
To better understand the following sections, we define some important terms in the WebAuthn protocol to have a common understanding.
Subscribe to our Passkeys Substack for the latest news, insights and strategies.
SubscribeResident keys (RKs) and non-resident keys (NRKs) are two types of cryptographic keys used in the WebAuthn protocol, and they differ primarily in their storage location and retrieval mechanism.
Definition:
Resident keys are stored directly on the authenticator itself. This could be a security key (e.g., YubiKey), a platform's secure enclave (e.g., iPhone's Secure Enclave), or a trusted platform module (TPM) on a laptop. Conditional UI (passkey autofill) only works for resident keys and the WebAuthn working group currently requires resident keys to be considered as a passkey.
Resident keys are often also called discoverable credentials, because the client can discover a list of possible keys from the authenticator that match the Relying Party ID (rpID) in question and show a list of possible / stored user handles (e.g. email, phone numbers, usernames) of the device.
In the following screenshot, you see a list of all resident keys (credential ID, rpID, username, display name) that are stored on a YubiKey. Non-resident keys are not in the list, as they are not stored on the authenticator:
Login flow:
Source: William Brown
During the login process, the Relying Party sends a request without specifying credentials to the client (browser) which starts to query the authenticator (here in the chart: security key). The authenticator discovers all resident keys for the corresponding Relying Party and the client (browser) selects the desired resident key. This resident key is used to sign the challenge. The signature is sent from the authenticator via the client to the Relying Party.
Advantages:
Disadvantages:
Use Cases: Ideal for devices where the user frequently authenticates, like personal smartphones or laptops.
Want to find out how many people can use passkeys?
View Adoption DataDefinition:
Non-resident keys, in contrast, are not stored on the authenticator. Instead, the authenticator generates a new key pair (based on its internally protected master key) and sends the public key of this new key pair to the server (Relying Party) together with the credential ID (that contains a seed) during sign-up. The server then associates this public key with the users account. For subsequent authentications, the authenticator re-derives the private key by receiving the credential ID, extracting the seed and combining it with the master key. Because the key is only temporarily available in the protected memory of the authenticator It is sometimes called ephemeral key in cryptographic language.
Non-resident keys are also often called non-discoverable credentials, because the authenticator cannot discover / search for keys for a specific Relying Party ID (rpID). Without the credential ID the authenticator does not even know that there might be a key.
Login flow:
Source: William Brown
During the login process, the Relying Party must first identify which user is requesting authentication (e.g. by asking for a user handle, e.g. email, phone number or username) and then sends the credential IDs that it is aware of for the requesting user to the client (browser). The client forwards them to the authenticator (here: security key). The authenticator uses the credential ID together with the authenticator's master key to derive the temporary private key, signs the challenge with the generated key and returns it to the client (here: browser), which forwards it to the Relying Party. Non-resident keys were originally used as second factor before the introduction of passkeys. Therefore, identifying the user first was part of the regular login process.
Advantages:
Disadvantages:
Use Cases: Ideal for roaming authenticators like security keys (e.g. YubiKeys) that are used across multiple services or platforms.
Imagine you have a security key (e.g. YubiKey), and you register it with two online services: Service A and Service B. For Service A, you use a resident key. For Service B, a non-resident key. When you authenticate to Service A, you simply tap your security key (e.g. YubiKey), and youre in - no need to specify a username. For Service B, youd first provide your username in the browser / native app. The service then sends the associated credential ID to your security key (e.g. YubiKey), which then re-generates the ephemeral private key for authentication.
In essence, while both resident and non-resident keys enhance security by leveraging cryptographic authentication, their user experiences and storage mechanisms differ, catering to varied use cases.
Want to experiment with passkey flows? Try our Passkeys Debugger.
Try for FreeConditional UI is a milestone feature of passkeys / WebAuthn. It takes even more burden from the user, as the user not only does not need to remember a password, but also does not need to remember the user handle (e.g. email, phone number, username) with which he signed-up to a Relying Party. Especially, in cases where Relying Parties' services are only occasionally used this is a huge step.
This works because as soon as the login page is opened, the Relying Party server sends a challenge in the background to the client (remember theres no credential ID required to be sent in this call). The client takes this challenge and checks which passkeys match the Relying Party ID on this authenticator and offers the selection via the autofill menu, where the user can select the appropriate passkey.
Moreover, it also saves the user from an extra click on the login button, because as soon as the passkey is selected from the autofill menu, the login process starts.
Conditional UI (passkeys autofill) only works for resident keys.
CTAP is a foundational protocol in the FIDO2 standard, bridging the communication gap between clients (like browsers) and authenticators (like security keys, e.g. YubiKeys, or smartphones). To better understand CTAP, lets have a first brief view at the different protocol versions before analyzing the impact on resident and non-resident keys.
The earlier version, often referred to as Universal 2nd Factor (U2F), was primarily designed for second-factor authentication. In U2F, the server provides a challenge, and the authenticator provides a response, proving possession of the private key. However, U2F doesnt support resident keys, meaning it always requires a server-side lookup to identify which key to use for a user, as this was part of the process when asking for a second factor.
The successor to U2F, CTAP2 introduced support for resident keys, allowing for passwordless and username-less authentication. With resident keys, the authenticator stores the users username and credential ID (together with the Relying Party ID), eliminating the need for the Relying Party server to supply it during authentication. This is a significant leap towards a more seamless UX.
However, CTAP2 comes with challenges. One notable issue is the management of resident keys. For instance, deleting a specific resident key in a CTAP2.0 device often requires a complete device reset (so also your master key is reset, meaning all your non-resident keys will no longer work either), which is not user-friendly and can be problematic in scenarios where multiple resident keys are stored on a single device. This makes resident keys on a CTAP2.0 device a serious commitment. You really dont want to accidentally fill up that limited space you often have, especially on security keys (e.g. YubiKeys).
CTAP2.1 is a subsequent version of CTAP2, bringing additional features and improvements to the protocol. Some key points about CTAP 2.1 include:
After having had a look at resident keys, non-resident keys and the different CTAP versions, we now analyze the Relying Party side and thus the WebAuthn server side in more depth.
WebAuthns flexibility (but also its complexity) are largely attributed to its server settings, particularly within the authenticatorSelection object. This object guides the client in selecting the right authenticator for the job.
This server option specifies how the authenticator is attached to the client device. It provides insights into how the authenticator communicates with the client:
Possible Values
Use Cases & Examples
In the WebAuthn Level 1 specification, this server option was called requireResidentKey and could hold the Boolean values true (the authenticator must create a resident key) or false (the authenticator must create a non-resident key). WebAuthn Level 2 replaced this server option with the new server option residentKey:
Possible Values
Use Cases & Examples
User verification refers to the process that ensures the person interacting with the authenticator is the legitimate owner, typically by requiring a specific authentication gesture like entering a PIN, providing a fingerprint, or using facial recognition.
Sometimes user presence (UP) is also mentioned or used similar to user verification but has some differences indeed. User presence only confirms that someone anyone is physically present and interacting with the device. It doesnt verify the identity of that person. A simple touch of a security key, without any further identity checks, can suffice for user presence. For passkeys / WebAuthn, the user always needs to be present.
Possible Values
Use Cases & Examples
Pattern
Example: A corporate application wants employees to log in without passwords on their company-issued laptops using built-in fingerprint readers. The credential is stored on the device, and the user must verify with a fingerprint each time.
Pattern
Example: A user registers a security key (e.g. YubiKey) for their online banking. They can use this key to authenticate on any device by providing the security key (e.g. YubiKey), without needing to enter a username.
Many hardware-based security keys (e.g. YubiKeys) have inherent storage constraints. This limitation is due to the physical memory available on the device and the design considerations of the manufacturer.
Example: A YubiKey might have the capacity to store only 20 resident keys. Once this limit is reached, no additional resident keys can be added without deleting existing ones.
Solution:
Different authenticators might handle resident key requests differently. Some might default to creating a resident key even if its not explicitly requested, while others might require explicit instruction.
The inconsistent behavior for different WebAuthn server options on different platform is a major problem. For instance, iOS will always create a resident key regardless of the WebAuthn server options passed to, while Android requires an opt-in (e.g. with residentKey: preferred or residentKey: required).
Besides the behavior, its even worse that based on the server-side stored data, you cannot say with 100% certainty if a stored credential is a resident key or non-resident key. Instead, you can follow some checks and narrow it down (see below), but still need to hope that the credentials behavior is according to your belief.
The reason behind is that theres a WebAuthn suggestion to store information about the kind of credential (resident key or non-resident key) in the credential properties extension (clientExtensionResults.credProps.rk which is either true or false). However, providing this information to the RP is not guaranteed as all WebAuthn extensions are optional, e.g. iOS doesnt send it (so you dont know if its a resident key or non-resident key).
During our research, we tried to test the behavior on different platforms and authenticators (Windows 10, Windows 11, Android 7, Android 13, iOS17, macOS Ventura, YubiKey) with two WebAuthn demo pages that provide more details on the created credentials: https://webauthn.io and https://webauthntest.identitystandards.io/. The latter offers the possibility to work with the legacy requireResidentKey property (WebAuthn Level 1) and even combine it with residentKey property (WebAuthn Level 2). However, the results were not reliable (e.g. it stated non-resident key for iOS but clearly conditional UI worked).
The most trustworthy checking scheme we found is the following:
As you can see, this helps to narrow it down, still the unknown option resides and you cannot determine the type of key with 100% certainty.
This is also in line with the findings of William Brown from SUSE in his great article outlining how security keys (e.g. YubiKeys) could be useless if resident keys are required by Relying Parties (we extended his table):
In the table, you see for different WebAuthn server resident key options if a resident key was created (true), if a non-resident key was created (false) or something else happened.
Solution:
If a user reaches the storage limit on their security key (e.g. YubiKey), they might face errors or be unable to register new credentials. This can lead to confusion and frustration.
Solution:
As youve seen above, the WebAuthn server settings you choose can significantly impact the user experience and security of your authentication process. It's essential to understand the nuances of these settings to make informed decisions.
Resident vs. Non-resident Keys: If a majority of your users primarily access your service from personal devices like smartphones or laptops, resident keys are a suitable choice. Resident keys are stored on the device itself and offer a seamless authentication experience for users who frequently use the same device. However, for users who use security keys (e.g. YubiKeys), which are non-resident keys, might be more appropriate.
User Verification (UV) Settings: Depending on the level of security you want to achieve, you can decide how stringent the user verification process should be. If you're aiming for high security, requiring a PIN, fingerprint, or facial recognition (userVerification: preferred or userVerification: required) is advisable.
Attestation and Trustworthiness: Attestation allows you to verify the origin and integrity of the authenticator. Decide if you want to trust all authenticators or only those from specific manufacturers. This can be crucial if you're dealing with sensitive data and want to ensure that only high-quality, trusted authenticators are used.
Fallback Mechanisms: Always have a fallback mechanism in place. If a user loses their authenticator or if it malfunctions, they should have an alternative way to access their account. This could be through backup codes, SMS verification, email magic links or other multi-factor authentication methods.
Continuous Education: The landscape of passkeys and WebAuthn is continuously evolving. Stay updated with the latest developments, vulnerabilities, and patches. Encourage your development team to participate in workshops, webinars, and conferences related to passkeys and WebAuthn.
User Onboarding and Education: When introducing passkey authentication, ensure that your users understand its benefits and how it works. Offer clear instructions during the sign-up process and provide resources (like FAQs or video tutorials) to assist users in setting up and using passkeys.
By adhering to these best practices, developers and product managers can ensure that they implement passkey authentication effectively, balancing both security and user experience.
If you want to implement passkeys for mainstream adoption in your website or app and dont need to support security keys (e.g. YubiKeys), as most of your users will just use their smartphone or laptop, we recommend the following settings.
Benefits:
WebAuthn's server settings, while being complex, offer a robust and flexible framework for authentication. Mastering these settings is crucial, as it's not just about implementing a new standard; it's about fundamentally improving the security and efficiency of user authentication.
In essence, understanding WebAuthn's server settings is an investment in building more secure, efficient, and forward-looking applications. As the digital landscape evolves, being well-versed in such technologies will be indispensable. To stay updated, join our passkeys community or subscribe to our newsletter below.
Table of Contents
Enjoyed this read?
🤝 Join our Passkeys Community
Share passkeys implementation tips and get support to free the world from passwords.
🚀 Subscribe to Substack
Get the latest news, strategies, and insights about passkeys sent straight to your inbox.
We provide UI components, SDKs and guides to help you add passkeys to your app in <1 hour
Start for free