WebAuthn - Documentation

What is WebAuthn?

WebAuthn (Web Authentication) is an API that enables strong, secure authentication for websites and web applications using public key cryptography. Instead of relying on passwords, WebAuthn leverages hardware security tokens like fingerprint scanners, security keys, or built-in authenticators on devices (e.g., Windows Hello, Face ID, Touch ID) to verify user identity. The API allows websites to verify the user’s possession of a private key corresponding to a public key registered with the website. This verification happens without the actual private key ever leaving the user’s device, significantly enhancing security. WebAuthn is standardized by the W3C and is supported by a growing number of modern browsers.

Benefits of WebAuthn

Security Considerations

While WebAuthn significantly improves security, developers still need to address crucial aspects:

WebAuthn vs. Traditional Password Authentication

Feature WebAuthn Traditional Password Authentication
Security Significantly stronger, resistant to many attacks Vulnerable to phishing, brute force, etc.
User Experience Often more convenient and seamless Can be cumbersome and prone to errors
Password Management No passwords needed, simplifying user experience Requires password creation, storage, and management
Phishing Resistance Highly resistant Highly susceptible
Complexity More complex to implement Relatively simpler to implement
Browser Support Growing rapidly, but may require fallback mechanisms Widely supported

WebAuthn API Basics

Key Concepts: Credentials, PublicKeyCredential, Authenticator

Understanding these core concepts is crucial for working with the WebAuthn API:

This method initiates the registration process, creating a new credential for a user on their authenticator. This is typically used when a user first registers with your website or adds a new authenticator.

The method takes an options object as an argument, which specifies the parameters for credential creation. Key parameters include:

The method returns a Promise that resolves with a PublicKeyCredential object upon successful registration. If registration fails (e.g., user cancellation), the Promise rejects. The server-side then needs to verify the PublicKeyCredential to complete the registration process. Error handling is critical to provide informative feedback to users and prevent vulnerabilities.

This method initiates the authentication process, verifying an existing credential associated with the user. It’s used when a user logs in.

The method takes an options object as an argument similar to create(), with key differences:

The method returns a Promise that resolves with a PublicKeyCredential object upon successful authentication. Like create(), if authentication fails (e.g., incorrect credentials, user cancellation), the Promise rejects. The server-side then verifies the PublicKeyCredential to confirm the user’s identity. The server needs to check if the id of the PublicKeyCredential matches a previously registered credential. Robust error handling is crucial here.

Credential Creation

Generating a New Credential

Generating a new WebAuthn credential involves a client-side and a server-side component. The client-side uses the navigator.credentials.create() API to initiate the process, while the server-side verifies the resulting attestation and stores the public key for later authentication.

The client-side process starts by constructing a PublicKeyCredentialCreationOptions object (detailed below). This object contains information about the relying party, the user, the desired cryptographic parameters, and other relevant settings. This object is then passed to navigator.credentials.create(), which prompts the user to register with their authenticator (e.g., security key, biometric sensor). The authenticator generates a new key pair, keeping the private key secure, and returns a PublicKeyCredential object to the client. This object contains the public key and an attestation statement, which proves that the key pair was created securely. This object is then sent to the server.

Understanding PublicKeyCredentialCreationOptions

The PublicKeyCredentialCreationOptions object is critical for configuring the credential creation process. Its key properties include:

Handling User Verification

WebAuthn supports various levels of user verification. The authenticatorSelection object in PublicKeyCredentialCreationOptions lets you specify requirements:

Attestation Types

The authenticator generates an attestation object that accompanies the PublicKeyCredential to prove the validity of the public key. Different attestation types exist:

The choice of attestation type influences the security level and the complexity of the server-side verification process. Consider the tradeoffs between security, complexity, and user experience when choosing an attestation type. Generally, stronger attestation types like Attestation CA provide a more secure approach.

Error Handling and Troubleshooting

Error handling is crucial for a robust WebAuthn implementation. The navigator.credentials.create() Promise might reject for various reasons:

Carefully handle these errors, providing informative feedback to the user. Log errors appropriately for debugging purposes. Consider providing alternative authentication methods for users who experience issues with WebAuthn. Thorough testing across various browsers, devices, and authenticator types is essential to ensure a smooth user experience. Debugging may involve inspecting the browser’s developer console to capture error messages and details about the registration or authentication process.

Credential Selection

Selecting an Existing Credential

Credential selection involves using an existing credential registered with your website for authentication. This is done using the navigator.credentials.get() API. Unlike credential creation, this process doesn’t generate a new key pair; it uses a previously registered key pair to verify the user.

The process begins on the client-side by constructing a PublicKeyCredentialRequestOptions object (explained below). This object provides information about the relying party, the challenge, and importantly, a list of allowed credentials. This list restricts authentication attempts to only previously registered credentials, enhancing security by preventing attackers from using stolen credentials. The PublicKeyCredentialRequestOptions object is passed to navigator.credentials.get(), prompting the user to select a registered credential using their authenticator. The authenticator then performs the authentication, and the client receives a PublicKeyCredential object containing the authentication information, which is then sent to the server for verification.

Understanding PublicKeyCredentialRequestOptions

This object is crucial for configuring the credential selection process. Key properties include:

User Verification in get

The userVerification property in PublicKeyCredentialRequestOptions controls the level of user verification required during authentication. Just as in credential creation, 'required' enforces user verification (e.g., biometric scan or PIN entry) by the authenticator. 'preferred' suggests but doesn’t mandate it, and 'discouraged' discourages it but doesn’t prevent it. For optimal security, using 'required' is strongly recommended. The server-side verification process will use the userVerification information in the response to determine if the authentication met the required level.

Resident Key Management

Resident keys are cryptographic keys stored securely within the authenticator. They offer better security against attacks compared to non-resident keys (which might be vulnerable if the authenticator is compromised).

The authenticatorSelection option in PublicKeyCredentialCreationOptions (during credential creation) allows you to influence whether a resident key is used:

Managing resident keys requires careful consideration of security tradeoffs. While offering increased protection, requiring resident keys might negatively impact the user experience, especially if users have limited compatible authenticators.

Error Handling and Troubleshooting

Similar to credential creation, error handling is essential for navigator.credentials.get(). The Promise might reject due to several reasons, including:

Handle these errors gracefully, providing informative error messages to the user. Thorough testing is critical to identify and resolve potential issues across different browsers, authenticators, and devices. Again, logging errors for debugging is highly recommended. If a user consistently experiences errors, consider providing fallback authentication mechanisms.

Server-Side Integration

Backend Requirements

The server-side plays a crucial role in WebAuthn, handling the verification of the PublicKeyCredential object received from the client and managing user credentials securely. Your backend needs to:

Verifying Credentials on the Server

The server-side verification process involves several steps:

  1. Receive the PublicKeyCredential object from the client: This object contains the client’s authentication data.

  2. Verify the challenge: Ensure the received challenge matches the challenge sent to the client earlier.

  3. Verify the signature: Verify the digital signature within the PublicKeyCredential using the received public key. This step confirms the authenticity of the response.

  4. Verify attestation (if applicable): Depending on the attestation type, verify the attestation object to ensure the key pair was generated by a trusted authenticator. This often involves checking digital certificates or other attestation statements.

  5. Check for credential ID: Check if the credential ID received in the PublicKeyCredential matches an existing credential in your database.

  6. Check userVerification (optional): Based on the specified userVerification requirement, check if the authenticator performed user verification.

  7. Update session state (if necessary): After successful verification, update your session state to indicate the successful login.

Storing Credentials Securely

Securely storing user credentials is paramount. Avoid storing private keys; only store the public key. Use a database with strong encryption and access controls. Consider these aspects:

Integrating with Existing Authentication Systems

Integrating WebAuthn with existing systems might require careful planning:

Example Implementations (Node.js, Python, etc.)

Providing specific example implementations for different languages would exceed the scope of a concise developer manual section. However, numerous libraries exist for various languages (Node.js, Python, PHP, etc.) that simplify WebAuthn server-side integration. Refer to the documentation of these libraries for specific implementation details. Popular examples include:

Remember to carefully review and understand the security implications of any library you choose before using it in a production environment. Always prioritize security best practices when implementing WebAuthn server-side integration.

Advanced Topics

Authenticator Selection Criteria

Fine-grained control over authenticator selection enhances security and user experience. The authenticatorSelection option within PublicKeyCredentialCreationOptions and PublicKeyCredentialRequestOptions allows you to specify preferences for the authenticator. Consider these criteria:

User Experience Best Practices

A well-designed user experience is vital for WebAuthn adoption. Consider these best practices:

Handling Multiple Authenticators

Users might have multiple registered authenticators. The allowCredentials array in PublicKeyCredentialRequestOptions lets you control which credentials are allowed for authentication. You can:

Platform-Specific Considerations

WebAuthn implementation might have subtle differences across platforms and browsers. Pay attention to these:

Future of WebAuthn

WebAuthn is continuously evolving. Future developments might include:

Staying updated with the latest WebAuthn specifications and browser implementations is crucial for building secure and user-friendly applications. Regularly review the W3C Web Authentication specification and the relevant browser documentation.

Troubleshooting and Debugging

Common Errors and Solutions

Several common errors can occur during WebAuthn implementation. Here are some examples and potential solutions:

Debugging Techniques

Effective debugging is crucial for resolving WebAuthn issues. Consider these techniques:

Browser Compatibility Issues

Browser compatibility is a critical aspect of WebAuthn. Test your implementation across a range of browsers (Chrome, Firefox, Edge, Safari) and browser versions. Some browsers might have different levels of support for specific WebAuthn features or might handle errors differently.

Use feature detection to gracefully degrade functionality for browsers that don’t fully support WebAuthn. Provide alternative authentication methods for users with incompatible browsers. Consult the official browser documentation for details on WebAuthn support in each browser.

Security Audits

Regular security audits are essential to ensure your WebAuthn implementation is robust and secure. Consider these aspects:

Addressing security concerns proactively reduces the risk of exploits and ensures a secure authentication experience for your users. WebAuthn significantly improves security compared to password-based authentication, but proper implementation and regular audits are still vital.

Appendix: Specifications and Standards

WebAuthn Specification

The Web Authentication API (WebAuthn) is a standard defined by the World Wide Web Consortium (W3C). The specification details the client-side and server-side interactions for secure authentication using public key cryptography. It outlines the API’s methods (navigator.credentials.create() and navigator.credentials.get()), data structures (like PublicKeyCredentialCreationOptions and PublicKeyCredentialRequestOptions), and security considerations. Key aspects covered include:

The official W3C Web Authentication specification is the definitive source of information. Regularly consult this document for updates and clarifications. Keep in mind that browser implementations might not always perfectly align with the latest specification, so testing across different browsers is essential.

CTAP Specifications

The Client to Authenticator Protocol (CTAP) specifications define the low-level communication protocol between the client (web browser) and the authenticator (security key or built-in authenticator). These specifications are crucial for understanding the underlying mechanisms that WebAuthn relies on. CTAP defines:

Understanding CTAP specifications helps in troubleshooting low-level communication issues between the client and the authenticator. However, for most WebAuthn development, directly interacting with CTAP is usually unnecessary, as the WebAuthn API handles these low-level details.

FIDO Alliance Resources

The FIDO (Fast Identity Online) Alliance is a non-profit organization that promotes open standards for strong authentication. The FIDO Alliance plays a significant role in developing and promoting WebAuthn and related specifications. Their resources are invaluable for developers:

Leveraging the FIDO Alliance resources helps developers stay updated with the latest advancements and best practices in WebAuthn development. Their website serves as a central hub for information and community engagement.