This tutorial explains how to use Selenium for automated E2E testing of passkey solutions in Node.js
Amine
Created: September 13, 2024
Updated: March 21, 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.
The most secure and most convenient passwordless authentication method are passkeys which are gaining prominence. While they bring a lot of benefits, they also present testing challenges due to their reliance on physical authenticators (e.g. Face ID, Touch ID, Windows Hello). Thankfully, Selenium's Virtual Authenticator enables developers to automate passkey flow testing without physical devices.
This blog post will guide you by answering some related questions:
In the following, you find some relevant background information to get you started.
WebAuthn-based passkeys are essential for building secure and convenient authentication flows. Testing them manually, however, can be time-consuming and error-prone, especially with different devices and user flows. Automating these tests ensures that your application works seamlessly under various scenarios, including:
With Selenium WebDriver, you can simulate these flows using a Virtual Authenticator, allowing for robust test automation across your web app.
Selenium is a powerful choice for automating passkey authentication testing due to several key advantages:
To ensure full compatibility for passkey testing, the following minimum browser versions are required for Selenium 4:
- **Chrome**: Version 75+ [[source]](https://www.selenium.dev/documentation/webdriver/browsers/chrome/). - **Firefox:** Version 78+ [[source]](https://www.selenium.dev/documentation/webdriver/browsers/firefox/). - **Safari**: **Safari**: For Safari versions 10 and above, SafariDriver comes bundled by default with the browser preinstalled in macOS. Earlier versions required the Safari WebDriver extension, which is no longer supported for testing. [[source]](https://www.browserstack.com/guide/run-selenium-tests-on-safari-using-safaridriver) - **Edge**: Version 79+ [[source]](https://www.selenium.dev/documentation/webdriver/browsers/edge/).
Selenium 3: While it's technically possible to use passkeys in Selenium 3, the lack of native support requires numerous workarounds and unconventional methods. A demonstration of this approach can be seen in this Youtube Video
Mocha is a JavaScript test framework known for running tests asynchronously. It supports both synchronous and asynchronous code, providing a flexible structure for test suites, making it a solid choice for Selenium-based end-to-end testing.
Overall, Selenium’s flexibility and reliability make it ideal for robust passkey testing across different platforms and scenarios.
The Virtual Authenticator in Selenium allows you to simulate roaming authenticators like hardware security keys ( e.g. YubiKeys) or built-in platform authenticators (e.g., Touch ID, Face ID) when testing WebAuthn flows. This feature is crucial for automating passkey registration and login processes without needing real physical devices.
Key aspects of the Virtual Authenticator:
How the Virtual Authenticator Handles Passkey / WebAuthn Challenges
The Virtual Authenticator in Selenium directly intercepts passkey authentication / WebAuthn challenges during testing. When a web application sends a challenge as part of a WebAuthn request, the virtual authenticator captures it, signs it with its configured private key, and returns the signed response to the application. This process mimics a real physical authenticator's handling of such challenges.
Before we dive into setting up the tests, ensure that you have the following tools and knowledge:
Required Libraries and Tools
Follow these steps to set up Selenium for automated passkey testing.
To interact with the browser using Selenium, install the selenium-webdriver
package via npm:
npm install selenium-webdriver
For structuring our tests, we’ll use Mocha. Install Mocha with:
npm install mocha
Mocha offers a flexible framework for organizing and running test suites, making it an excellent choice for Selenium-based end-to-end testing.
Now, let’s create a basic test script using Mocha and Selenium WebDriver. This test will include WebAuthn interaction via a virtual authenticator.
Create a test file namedtest.spec.js
and add the following code to interact with the browser, perform basic navigation,
and execute fundamental Passkey Creation and Authentication:
test.spec.jsconst {Builder, By, until} = require("selenium-webdriver"); const { VirtualAuthenticatorOptions, Transport, Protocol, } = require("selenium-webdriver/lib/virtual_authenticator"); const mocha = require("mocha"); const {describe, it, before} = mocha; describe("Passkey Authentication Tests", function () { this.timeout(10000); const timeOut = 5000; let driver; before(async function () { driver = await new Builder().forBrowser("chrome").build(); // Set up the virtual authenticator with the desired options let options = new VirtualAuthenticatorOptions(); options.setProtocol(Protocol.CTAP2); options.setTransport(Transport.INTERNAL); options.setHasUserVerification(true); options.setIsUserVerified(true); options.setHasResidentKey(true); // Add the virtual authenticator to the WebDriver await driver.addVirtualAuthenticator(options); }); it("should load the login page", async function () { await driver.get("https://passkeys.eu"); const emailField = await driver.wait( until.elementLocated(By.id("email")), timeOut ); await emailField.sendKeys(`test+${Date.now()}@test.com`); await emailField.submit(); await driver.wait( until.elementLocated(By.className("cb-passkey-list-container")), timeOut ); }); });
Run the test using Mocha:
npx mocha test.spec.js
The test opens a Chrome browser window and automatically navigates to https://passkeys.eu
It then types in a randomized email and submits it
This will trigger the passkey challenge, which the virtual authenticator will handle automatically.
Finally, you're successfully logged in and can view the newly created passkey.
To maximize the potential of Selenium WebDriver for simulating user actions and detecting DOM changes, explore their documentation thoroughly. Focus on these crucial areas:
Moreover, dive into Mocha's Getting Started guide. Pay close attention to these essential concepts:
We now teach how to configure the Virtual Authenticator in Selenium WebDriver to simulates authenticators.
Setting Up the Virtual Authenticator
The following code demonstrates how to configure a virtual authenticator for passkey testing. This example will simulate the CTAP2 protocol with internal device transport.
Initialize Virtual Authenticator Options:
const { VirtualAuthenticatorOptions, Protocol, Transport } = require('selenium-webdriver/lib/virtual_authenticator'); let options = new VirtualAuthenticatorOptions(); options.setProtocol(Protocol['CTAP2']); // CTAP2 for passkey authentication options.setTransport(Transport['INTERNAL']); // INTERNAL transport for built-in authenticators options.setHasUserVerification(true); // Supports user verification options.setIsUserVerified(true); // User is verified options.setHasResidentKey(true); // Supports resident keys
setProtocol(Protocol['CTAP2'])
: Configures the virtual authenticator to use
the CTAP2
protocol, which is necessary for passkey operations.setTransport(Transport['INTERNAL'])
: Simulates an authenticator built into the platform, such as a mobile
device or laptop.setHasUserVerification(true)
: Indicates that the authenticator can verify the user's identity, essential for
secure authentication processes.setIsUserVerified(true)
: Simulates a scenario where the user has already been verified by the authenticator.
when set to false it mimics an authentication failure, such as when a user cancels the passkey input. Note that
this setting is effective only when setHasUserVerification is true.setHasResidentKey(true)
: Enables the virtual authenticator to
support resident keys, which are credentials stored directly on
the device (contrary to non-resident keys).These options help you simulate a complete passkey authentication scenario in a test environment, ensuring that your application handles these flows correctly.
Add the Virtual Authenticator to the WebDriver:
await driver.addVirtualAuthenticator(options);
This setup will simulate a passkey scenario where the user is verified and resident keys are supported. You can add this authenticator to your Selenium WebDriver to test passkey authentication.
If you are using a version of Selenium WebDriver earlier than 4.3.0, you will need to upgrade to at least this version to access the Virtual Authenticator feature and ensure your tests can fully simulate passkey authentication scenarios (Release Notes).
Passkey registration is the first step in a passkey authentication flow. The following test simulates user interaction during the registration process and verifies that the passkey is successfully created.
it('should successfully register a passkey', async function () { await driver.get('https://yourapp.com/register'); // Change the URL to your registration URL const registerButton = await driver.findElement(By.id('registerPasskeyButton')); // Change this to find the passkey append trigger await registerButton.click(); // Simulate passkey registration const successMessage = await driver.wait( until.elementLocated(By.xpath("//*[contains(text(),'Passkey successfully registered')]")), 5000 ); // Change the locator to your success indicator in the HTML assert.strictEqual(await successMessage.isDisplayed(), true); });
Once registered, a user should be able to log in using their passkey. Here’s a test case for validating the passkey login flow:
it('should log in with passkey', async function () { await driver.get('https://yourapp.com/login'); // Change the URL to your login URL const loginButton = await driver.findElement(By.id('loginWithPasskeyButton')); // change this to your passkey login trigger await loginButton.click(); // Simulate passkey authentication const loggedInText = await driver.wait( until.elementLocated(By.xpath("//*[contains(text(),'Welcome, you are logged in')]")), // Change this to locate your login success indicator 5000 ); assert.strictEqual(await loggedInText.isDisplayed(), true); });
WebAuthn interactions may fail for various reasons, such as incorrect user verification or unsupported devices. You can simulate these failures in your tests and ensure that your application handles them correctly.
Simulating User Verification Failure
In this example, we simulate a scenario where the user verification fails during passkey login:
it('should handle failed passkey authentication', async function () { await driver.get('https://yourapp.com/login'); await driver.setUserVerified(false); // Simulate failed [user verification](/blog/webauthn-user-verification) const loginButton = await driver.findElement(By.id('loginWithPasskeyButton')); await loginButton.click(); const failureMessage = await driver.wait( until.elementLocated(By.xpath("//*[contains(text(),'Passkey authentication failed')]")), 5000 ); assert.strictEqual(await failureMessage.isDisplayed(), true); });
Network issues, such as timeouts, can disrupt passkey authentication flows. Although the WebDriver doesn't allow for direct network simulation, you can simulate network failures in your tests by altering the API endpoint or manipulating localStorage data in the browser (if your application stores such data there).
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 CommunitySimulating a Network Timeout
Here’s an example of how to simulate a network timeout by changing the API URL stored in the browser’s local storage:
await driver.executeScript(` window.localStorage.setItem('apiUrl', 'https://fake-endpoint.com'); `);
This method allows you to test how your app handles network-related issues during authentication processes.
Selenium WebDriver's Virtual Authenticator provides a robust tool for automating passkey-related authentication flows in web applications. By simulating various scenarios - including successful registration, login, and authentication failures - developers can ensure their applications are resilient and handle most WebAuthn interactions correctly.
The next step is to integrate these tests into your CI/CD pipeline, enabling continuous validation of your passkey authentication processes.
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
Passkeys E2E Playwright Testing via WebAuthn Virtual Authenticator
Anders - March 30, 2024
Testing Multi-Device Passkey Login with Corbado and ngrok
Nicolai - May 31, 2023
Table of Contents