webauthn-user-id-userhandleWebAuthn Know-How

WebAuthn User ID, User Handle, User Name and Credential ID

Understand WebAuthn User ID, User Name, User Display Name, User Handle and Credential ID in Passkey applications and get advice for implementation.

Blog-Post-Author

Vincent

Created: December 14, 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.

1. Introduction

2. Understanding the WebAuthn Terminology

    2.1 What's the WebAuthn Credential ID?

      2.1.1 Credential ID of Resident Keys (Discoverable Credentials)?

      2.1.2 Credential ID of Non-Resident Keys (Non- Discoverable Credentials)

    2.2 What's the WebAuthn User ID (user.id)?

    2.3 What's the WebAuthn User Handle (response.userHandle)?

    2.4 What's the WebAuthn User Display Name (user.displayName)?

    2.5 What's the WebAuthn User Name (user.name)?

    2.6 Overview of Storage Requirements and Authenticator Limits?

    2.7 FAQ

      2.7.1 Can the User ID be Empty or NULL?

      2.7.2 Whats the Difference Between User Name and User Display Name in WebAuthn?       2.7.3 How Can I Implement Usernameless / Accountless Authentication?

      2.7.4 What Data can be Changed Client-Side (on the Authenticator)?

3. The Complexities and Challenges

    3.1 Complications in WebAuthn Specifications (Level 2 vs. Level 3)

    3.2 Limit the Number of Credentials Per Authenticator Per Relying Party

    3.3 User Handle Should Not Expose Private Information

    3.4 Confusing Lookup of Credentials in AllowCredentials

    3.5 Confusing UI for User Name and User Display Name when Deleting Passkeys

    3.6 How does AllowCredentials work with User ID, User Name or User Display Name?

    3.7 How does ExcludeCredentials work with User ID, User Name or User Display Name?

4. Developer Recommendations for Passkey Implementation

    4.1 User ID Should Never be an Email Address / Phone Number

    4.2 Provide Human-Readable Names Instead of Only Providing Credential IDs for Passkeys

    4.3 Leverage User Name as a RP for Differentiating Credentials

    4.4 Conditional UI Mostly Uses User Names

5. Conclusion

1. Introduction

Passkeys and the underlying WebAuthn protocol form the new standard of secure and user friendly authentication for web and native apps. To securely and efficiently implement passkeys-based authentication, its of utmost importance to understand the details of user IDs, user names, display names, user handles, and credential IDs in this context. These elements play an important role and can easily be misunderstood causing large efforts to fix them if they were initially implemented the wrong way.

This blog post should help developers and product managers alike to better understand what these specific terms (WebAuthn Credential ID, User ID, User Handle, User Display Name, User Name) mean, how they differ, what makes it challenging and whats the industry-recommended way of implementing them.

Our focus here is not merely on definitions but on the relationships and operational complexities these terms entail. Why is understanding the difference between a 'User Name' and a 'User Display Name' more than an academic exercise? How does the choice of a 'User Handle' affect the privacy and security of your users? These are the questions we aim to answer.

In a field marked by rapid innovation and technical intricacies, staying ahead means not only keeping pace with current trends but also anticipating future developments.

Let's embark on this journey together, unraveling the complexities, understanding the challenges, and embracing the innovations in the world of WebAuthn and passkey applications.

2. Understanding the WebAuthn Terminology

Understanding the different terms is very important. In the following, we explain in more depth and also use a practical example situation to make things more tangible.

Example situation:

Lets say you want to create a new account at a passkey-enabled website. Your real name is John Doe (fullName) and your email address is john.doe@mail.com (loginEmail). The website is accessible at https://www.acme.com and it requires to sign-up with an email address, so that they can send you more emails regarding their product.

Assume that the very simplified backend database would look like this, storing all users in user and all passkeys in passkey table:

Passkey User Credential Table Scheme

In brackets we added which WebAuthn ceremony field corresponds to which database field. Keep in mind that a lot of relevant fields are missing, as this scheme is just to explain the relationship of the most important values: credentialId, user.id, user.name, user.displayName and response.userHandle.

Additionally, the following JSON shows a response during an authentication (login) ceremony that is sent from the authenticator to the relying party:

{ "id": "5W2vmAU1Mg5vkwzkxRNMdEZwnbrietMwFPdayOdpGkA", "rawId": "5W2vmAU1Mg5vkwzkxRNMdEZwnbrietMwFPdayOdpGkA", "type": "public-key", "response": { "authenticatorData": "t8DGRTBfls-BhOH2QC404lvdhe_t2_NkvM0nQWEEADcFAAAAAQ", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiRUdZdEFNZ2k4QjJFeTFGTlZmVkY5M201TEV6X0Nmd1R5MDBXMnpvUEVONCIsIm9yaWdpbiI6Imh0dHBzOi8vb3BvdG9ubmllZS5naXRodWIuaW8iLCJjcm9zc09yaWdpbiI6ZmFsc2V9", "signature": "Dei3zdjUf9oOcwuaxLc9y0zGfKvP9WHLqH3lInnxPPYsCkG_bs8bI-YjIWMHvlLkYua9RUajvK6qmbW8WiVLBlZ89a9Yy_XLCbSEyrUFjAyq_-awNeBObNRZ5woMIf1ntg8eH2O2HgvDuj1yk9u4WVbp93yZPX3e7NiCJ9d9i-wImNzIdnGN1ujX814fL9o3fys1vWSA6U8y4bvzgOk1Y58Bi7T6NpCI0ar7u73JsXEaDnexfBi1UooqOyfExyhRD4DeB5lk5kLVI_ONqcSfUASxgrjzHIoF5IsnV0cOlP7P3tKqtHCKcNd1JIknifp9tTy1EhFek4KBid-M8D8NAQ", "userHandle": "d2luZG93cyAxMSBjaHJvbWUgMTIw" }, "authenticatorAttachment": "platform" }

2.1 What's the WebAuthn Credential ID?

The WebAuthn Credential ID is a unique ID generated by the authenticator (e.g. your smartphone, laptop or hardware security key like YubiKey) during the registration (sign-up) process of a new credential (passkey). This Credential ID is required for passkey authentication, as it is used to distinguish individual credentials (passkeys). Each Credential ID is exclusive to a specific credential (passkey).

2.1.1 Credential ID of Resident Keys (Discoverable Credentials)

In case of resident-keys (discoverable credentials), the Credential ID is stored by the authenticator. When a user attempts to authenticate, the authenticator provides the Credential ID to the relying party to indicate which credential (passkey) is being used. Moreover, theres a limit: at most one discoverable credential per User ID (user.id) per relying party can be stored.

2.1.2 Credential ID of Non-Resident Keys (Non-Discoverable Credentials)

In case of non-resident keys (non-discoverable credentials), the Credential ID is stored by the relying party server. When a user attempts to authenticate, the user needs to manually select the Credential ID in a dialogue of the relying party. If just one non-resident key is available, this one will be sent to the client.

Example: "5W2vmAU1Mg5vkwzkxRNMdEZwnbrietMwFPdayOdpGkA"

Can it be changed?: No

Pre-defined format: No

Suggested value: Given by authenticator

Ben Gould Testimonial

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 Community

2.2 What's the WebAuthn User ID (user.id)?

The WebAuthn User ID (user.id) is an ID specified by the relying party (RP) to represent a user account within their system. In the context of passkeys, the User ID (user.id) plays a crucial role in linking a particular user with their credentials (passkeys).

During the registration process, the RP provides the User ID (user.id) to the authenticator, which then binds this User ID (user.id) to the newly created credential (passkey). This binding is essential for the authenticator to differentiate between different users credentials (passkeys), especially in multi-user environments. The User ID (user.id) should be unique for each user within the context of the RPs system and is therefore the same for all registered credentials (passkeys), ensuring a consistent and secure user identification process throughout the authentication lifecycle.

Example: d2luZG93cyAxMSBjaHJvbWUgMTIw

Can it be changed?: No

Pre-defined format: No

Suggested value: Primary key of user in RPs system (unique ID, UUID, autoinc)

2.3 What's the WebAuthn User Handle (response.userHandle)?

The User Handle (response.userHandle) , is another critical piece in passkey authentication. It is chosen by the relying party and is meant to represent the user account within their system.

The User Handle (response.userHandle) is returned in the response of the authenticator which is sent back to the relying party. It is equal to User ID (user.id). Thats why it is called User ID (user.id) when the user is created on the relying party server but when the authenticator responds, it sets the User Handle (response.userHandle) to the value of User ID (user.id).

The User Handle (response.userHandle) is associated with the credentials (passkeys) registered by a user and, for resident keys (discoverable credentials), is stored by the authenticator.

Its primary function is to enable the authenticator to map a set of credentials (passkeys) to a specific user account. Unlike the Credential ID, the User Handle (response.userHandle) is not necessarily unique as multiple Credential IDs can be associated with the same User Handle (response.userHandle).

A secondary use of the User Handle (response.userHandle) is to allow authenticators to know when to replace an existing resident key (discoverable credential) with a new one during the registration ceremony. In this context, excludeCredentials can be used to prevent the replacement of existing credentials (passkeys). Specific error messages are shown if the excludeCredentials list matches any of the locally on the authenticator available credentials (passkeys). However, even in this matching case, the WebAuthn registration ceremony is still triggered (meaning that the Face ID, Touch ID or Windows Hello popup appears). The reason why this popup appears, even though it fails in the matching case, is that for privacy reasons, the user needs to successfully sign the challenge before the authenticator and relying party tell the users that there is already a credential (passkeys).

Example: d2luZG93cyAxMSBjaHJvbWUgMTIw

Can it be changed?: No

Pre-defined format: No

Suggested value: Primary key of user in RPs system (unique ID, UUID, autoinc)

2.4 What's the WebAuthn User Display Name (user.displayName)?

The WebAuthn User Display Name (user.displayName) is a user-friendly, readable name chosen by the user during the registration process. This name is typically used for display purposes within the application interface and is not used for authentication.

The primary purpose of the User Display Name (user.displayName) is to enhance the user experience by providing a recognizable and human-readable identifier for the user, which can be their real name, a nickname, or any other preferred designation. It's important for developers and product managers to note that the User Display Name (user.displayName) is for convenience and personalization and should not be relied upon as a secure identifier for authentication processes.

It's recommended that the relying party should not restrict the users choice for User Display Name (user.displayName) more than necessary.

Example: John Doe

Can it be changed?: Yes

Pre-defined format: No

Suggested value: Full given and family name

2.5 What's the WebAuthn User Name (user.name)?

The WebAuthn User Name (user.name) serves to distinguish between user accounts, particularly in scenarios where multiple accounts might have similar or identical User Display Names (user.displayName). It is a unique ID within the RP's system, and unlike the User Display Name (user.displayName) , it is used in the authentication process. The User Name (user.name) can be an email address, a specific username, or any other form of unique ID chosen by the user or assigned by the system.

In the context of passkeys, the User Name (user.name) is crucial for linking a specific user account to its credentials (passkeys) and for ensuring the integrity of the authentication process, especially when dealing with user accounts that share similar User Display Names (user.displayName).

User name (user.name) can be arbitrary strings, not necessarily only email addresses, phone numbers or usernames.

Example: john.doe@mail.com

Can it be changed?: Yes

Pre-defined format: No

Suggested value: Primary identification (most likely email)

2.6 Overview of Storage Requirements and Authenticator Limits

The following table outlines a short summary which storage requirements for the RP database should be taken into account together with the storage limitations of authenticators.

WebAuthn Relying Party Database Authenticator Limits

2.7 FAQ

2.7.1 Can the User ID be Empty or "NULL"?

Technically, the WebAuthn specification does not explicitly forbid a NULL value for user.id (empty values are forbidden though). However, in practice, it's highly recommended to use a non-NULL User ID (user.id). This is because the User ID (user.id) is intended to uniquely identify a user on the server. A NULL value would not serve this purpose and could lead to ambiguities or security issues.

Implications for Resident Keys (Discoverable Credentials):

These are stored on the authenticator and can be used to authenticate a user without prior knowledge of the User ID (user.id). However, the User ID (user.id) is still important as it allows the server to identify the user once the Credential ID is presented.

Implications for Non-Resident Keys (Non-Discoverable Credentials):

These require the user to be authenticated first. In this case, the User ID (user.id) helps the server to fetch the correct Credential ID and public key for the user to complete the authentication process and return the Credential ID.

In summary, while it might be technically possible to have an empty User ID (user.id), it is not advisable due to the potential for confusion and security implications. The User ID (user.id) plays a crucial role in both discoverable and non-discoverable credentials, helping to ensure that the right user is authenticated with the correct credentials.

2.7.2 What's the Difference Between User Name and User Display Name?

User Name (user.name) is typically the user's unique login identifier within your system (e.g. the email address). This value is crucial for the relying party (RP) to distinguish between different user accounts.

Contrarily, the User Display Name (user.displayName) is meant for display purposes and is more user-friendly. It's often the user's full name or a name that the user prefers to be addressed by. This is the name shown to the user in various interfaces, like browser prompts or password managers, making the authentication experience more personalized and understandable.

Misconfiguration of these values can lead to user confusion or identification issues. It's important for an RP to accurately configure User Name (user.name) and User Display Name (user.displayName) to ensure a seamless user experience. Incorrect settings might make it challenging to identify the context or the specific account a passkey is associated with, especially in environments with multiple deployments or user accounts.

2.7.3 How can I Implement Seamless / Accountless Authentication?

Usernameless / accountless authentication represents a modern approach to user verification that removes the need for traditional usernames. Instead, it relies on cryptographic credentials (passkeys).

To implement usernameless authentication in your system, you need to follow these steps:

  1. Add passkey authentication to your system.
  2. Enable support for resident keys (discoverable credentials). These are credentials stored on the authenticator that can be used without requiring the user to input a username.
  3. During user registration, create a passkeys with therequireResidentKey property set to true. This ensures that the credential is stored on the authenticator, facilitating usernameless authentication.
  4. Modify the login flow to support Conditional UI that creates an authentication request that does not require the user to enter a username. The authenticator responds with the stored credential, which includes a unique user identifier allowing the server to recognize the returning user.
  5. Update backend logic to handle usernameless authentication. Ensure the server can correctly process the User Handle (response.userHandle) returned by the authenticator to retrieve the corresponding user account.

2.7.4 What Data can be Changed Client- Side (on the Authenticator)?

Changing passkey meta-data on the client side is something that is quite complex as its not guaranteed that changes are reflected on the server-side (and vice versa). Especially deleting passkeys on the server-side is not really propagated to the client-side causing a potentially bad user experience. Currently, the workaround to change the User Name (user.name) and / or User Display Name (user.displayName) looks like that you create a new passkey for this relying party with new values for User Name (user.name) and / or User Display Name (user.displayName). While doing so you need to make sure that you use the same User ID (user.id), which would overwrite the old passkey.

However, theres a recent WebAuthn explainer that suggests to add new functions to the WebAuthn API to propagate server-side deleted passkeys to the client and update User Name (user.name) as well as User Display Name (user.displayName), which is relevant especially in Conditional UI cases. Read more here.

Slack Icon

Become part of our Passkeys Community for updates and support.

Join

3. The Complexities and Challenges

This section delves into these complexities that emerge when implementing passkey based authentication systems and dealing with User IDs, User Names, User Display Names, User Handles and Credential IDs.

3.1 Complications in WebAuthn Specifications (Level 2 vs. Level 3)

The current draft of the Level 3 version also contradicts itself when it comes to the handling of the assertion on the relying party after successful local authentication. These differences in how credentials and user identification are handled can be seen by comparing sections 1.3.3 and 7.2 (6+7) of the WebAuthn Level 3 draft.

1.3.3 Flow:

The server examines the assertion, extracts the Credential ID, looks up the registered credential public key in its database, and verifies the assertion signature.

If valid, it looks up the User ID (user.id) associated with the assertions Credential ID. This User ID (user.id) is now authenticated. The server now does whatever it would otherwise do upon successful authentication - return a success page, set authentication cookies, etc.

If the Credential ID is not recognized by the server (e.g., it has been deregistered due to inactivity) then the authentication has failed. Each relying party will handle this in its own way.

7.2 (6+7) Flow:

Its crucial to determine if the user was identified before or not as the two cases differ:

  1. If the user was identified before the authentication (login) ceremony was initiated, e.g., via a provided username or cookie, verify that the identified user account has a credential (passkey) whose Credential ID equals the credential.rawId of the assertion. If the User Handle (response.userHandle ) is present, verify that it equals the User Handle (response.userHandle) of the user account.
  2. If the user was not identified before the authentication (login) ceremony was initiated, you need to verify that the User Handle (response.userHandle) is present. Verify that the user account identified by the User Handle (response.userHandle) is linked to a credential (passkeys) whose Credential ID equals credential.rawId.

As you can see, the big difference between section 1.3.3 and section 7.2 of the WebAuthn specification is that in 1.3.3 the Credential ID is first used to query the credential (passkey) table, while in 7.2 the User Handle (response.userHandle) is used (especially in case B) to query the user table before checking the credential (passkey) table.

3.2 Limit the Number of Credentials Per Authenticator Per Relying Party

A critical aspect of WebAuthn is the management of User Handles (response.userHandle) and credentials. The WebAuthn RFC 5.4.3 outlines that authenticators map pairs of relying party IDs and User Handles (response.userHandle) to public key credential sources. This mapping dictates that an authenticator stores only one discoverable credential per User Handle (response.userHandle) per Relying Party. The challenge lies in the security and uniqueness of User Handles (response.userHandle). Authenticators must know when to replace an existing discoverable credential with a new one during the registration ceremony, a process that requires careful handling to maintain security and user privacy.

3.3 User Handle Should Not Expose Private Information

Maintaining privacy and security in the WebAuthn framework is paramount. The User Handle (response.userHandle), being a key component in the authentication process, must be handled in a way that it does not reveal private information. The RFC suggests that User Handles (response.userHandle) should be unique account-level identifiers and cautions against using direct hash transformations of sensitive data, which could lead to security vulnerabilities.

3.4 Confusing Lookup of Credentials in AllowCredentials

The Credential ID plays a central role in the authentication ceremony. It is generated by the authenticator and must be unique for each credential. This uniqueness is critical when returning signatures valid for a specific account in an AllowCredentials context. The challenge lies in correctly implementing the lookup mechanism for Credential IDs based on provided identification information (e.g., email or username). This process becomes more intricate when dealing with empty AllowCredentials, where the correct approach involves looking up the Credential ID in the database, then determining login feasibility based on existing or deleted user accounts.

3.5 Confusing UI for User Name and User Display Name when Deleting Passkeys

Often the User Name (user.name) and User Display Name (user.displayName) in the browsers or password managers user interfaces do not provide the context you would need to securely analyze or delete the right passkeys. This makes it complex for users to distinguish between the right passkeys and can potentially lead to passkeys being deleted by accident.

3.6 How does ExcludeCredentials work with User ID, User Name or User Display Name?

AllowCredentials specifies the list of credentials (passkeys) that are allowed to authenticate the user. This list contains Credential IDs that the server is aware of and associates with the user's account. During authentication, the authenticator only returns signatures that are valid for the credentials listed in AllowCredentials. This ensures a secure and specific authentication process, linking the authentication attempt directly to the intended user account.

Changing the User ID (user.id), User Name (user.name) or User Display Name (user.displayName) does not impact the AllowCredentials process directly. This is because AllowCredentials focuses on Credential IDs rather than user User ID (user.id), User Name (user.name) or User Display Name (user.displayName).

3.7 How does ExcludeCredentials work with User ID, User Name or User Display Name?

ExcludeCredentials is used to prevent the creation of a new credential for a user if that user already has a registered credential on the authenticator. It's a security measure to avoid multiple registrations of the same user on the same device.

ExcludeCredentials contains a list of Credential IDs that are already registered for the user. During the registration process, the authenticator checks this list against the new credential it is about to create. If the new credential's ID matches any in the ExcludeCredentials list, the registration is halted to prevent duplication.

ExcludeCredentials operates on the basis of Credential IDs and does not directly interact with User ID (user.id), User Name (user.name) or User Display Name (user.displayName). Its primary function is to check for the uniqueness of the credential (passkey) being registered, not to validate user information.

Substack Icon

Subscribe to our Passkeys Substack for the latest news, insights and strategies.

Subscribe

4. Developer Recommendations for Passkey Implementation

4.1 User ID Muster Never be an Email Address / Phone Number

The User ID (user.id) was created to allow the relying party to have control over how the primary key of the user database looks like. Its considered to be very bad practice to use anything else than a primary key as User ID (user.id), as the User ID (user.id) never changes in WebAuthn from a technical point of view. Whereas in reality, its quite a common scenario to have changing email addresses or phone numbers being reassigned after a period of inactivity. Therefore, the User ID (user.id) must never contain any personally identifying information about the user and thus must never be an email address or phone number. Moreover, the User ID (user.id) must never be empty, though it maybe null. Assigning a non-descript, unique identifier to each user account enhances security and maintains user privacy

4.2 Provide Human-Readable Names Instead of Only Providing Credential IDs for Passkeys

Enhancing UX is key when dealing with passkeys. One effective way is to provide human-readable names for these credentials. This allows users to easily distinguish between different passkeys, especially if they have multiple. Here are some specific suggestions:

  • Allow users to edit the names of the credentials (passkeys). This gives users the flexibility to adopt their own naming conventions, enhancing their experience and making it easier to manage credentials (passkeys).
  • Suggest default names based on the ecosystem or device where the passkey was created, such as Windows Hello, 1Password, iCloud Keychain, or Chrome on macOS. You can also use the user agent to suggest names like Windows 10 passkey #1. These context-based names help users quickly identify the purpose and origin of each passkey.

4.3 Leverage User Name as a RP for Differentiating Credentials

As highlighted by Matthew Miller, it's recommended for a Relying Party (RP) to use User Name (user.name) as a unique identifier (besides User ID). This allows users to easily recognize and manage their passkeys in various user interfaces. Although some clients and operating systems might support User Display Name (user.displayName), its more reliable to count on the User Name (user.name) as the identifier regularly shown to users. This practice ensures consistency across different platforms and enhances the manageability of credentials.

4.4 Conditional UI Mostly Uses User Names

Implement Conditional UI that supports the User Name (user.name), such as an email address or username, or other provided identification information to retrieve potential Credential IDs. This approach is particularly useful in configuring the AllowCredentials option in PublicKeyCredentialRequestOptions. Since the exact Credential ID used for authentication might not be known in advance, using the User Name (user.name) as a hint can streamline the authentication process.

5. Conclusion

As we've navigated the complexities of WebAuthn User ID, User name, User Display Name, User Handle and Credential ID in passkey applications, the importance of the right understanding and correct implementation is clear. We hope that we could have clarified some of the confusing parts. To stay ahead in this rapidly evolving field, feel free to subscribe to our passkeys Substack or join or passkeys community on Slack.

Share this article


LinkedInTwitterFacebook

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