Understand WebAuthn User ID, User Name, User Display Name, User Handle and Credential ID in Passkey applications and get advice for implementation.
Vincent
Created: December 14, 2023
Updated: April 30, 2025
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.
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.
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:
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" }
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).
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.
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
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 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)
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)
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
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)
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.
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.
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.
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:
response.userHandle
) returned by the authenticator
to retrieve the corresponding user account.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.
##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:
response.userHandle
) of the user account.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.
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.
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.
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.
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.
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
).
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.
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
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:
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.
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.
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.
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.
Related Articles
WebAuthn Relying Party ID (rpID) & Passkeys: Domains & Native Apps
Vincent - September 21, 2023
WebAuthn Conditional UI (Passkeys Autofill) Technical Explanation
Vincent - October 20, 2023
Table of Contents