Migrating to Passkeys

On this page

This tutorial explains techniques you can use to ensure business continuity when migrating from password to passkey logins with the Curity Identity Server. By following these steps, your entire user base will continue to reliably authenticate and you won't block any users. We also provide an example deployment, which you can run on a development computer to understand the authentication flow and evaluate the passkeys user experience.

Categorize Users

It is recommended to classify users based on their authentication method and whether they are new or existing, since new users may need to onboard using a self-signup flow. The following sections explain an approach for meeting your requirements for each user type.

User TypeDescription
Existing + PasswordExisting users who want to continue to use password logins.
Existing + PasskeyExisting users who want to upgrade to passkey logins.
New + PasswordFuture users who register and want to use password logins.
New + PasskeyFuture users who register and want to use passkey logins.

Enable Passkeys

Start by adding a new Passkeys Authenticator and presenting an authentication selection screen. This enables passkey logins while continuing to support password logins:

Authentication Selection

Password Users

Existing users who authenticate using passwords can continue to select the password login option, to invoke the HTML form authenticator. If future users need to run a self-signup flow and create a password they can use the Create Account link on the HMTL form's login page. Therefore it is straightforward to continue to support password users:

Password Users

Users who Upgrade to Passkeys

When an existing user selects the passkeys option there will be a prompt to register a passkey. This will result in the Curity Identity Server storing a public key against the user's account. Therefore, the user must first authenticate, which requires you to configure a registration authenticator for the passkeys authenticator. A convenient option is to use email verification for passkey registration, though you can use any other authenticator:

Registration Authenticator

The user must then verify their email, after which the passkeys registration ceremony is performed, to create a passkey. If the user ever loses their passkey, or if they roam to another browser or device and the passkey is not synchronized, the user can run the passkey registration ceremony again. This enables users to quickly recover and sign in with their new passkey.

When you use the registration authenticator it identifies the existing user's account. The Curity Identity Server then stores the passkey's public key against that user account. Whenever the user authenticates with their passkey, the Curity Identity Server identifies the same user account, which ensures that it issues the same subject to OAuth tokens.

New Users with Passkeys

In some use cases, you may also need to run a self-signup flow for future users who want to use passkey logins. Do so by creating a passkeys registration sequence for users who want to sign up and then log in with passkeys. You usually need to implement some dynamic processing that first identifies new users and then creates an account. You can see one possible flow in the following diagram:

This example flow continues to use the built-in registration form for password users and uses a custom registration form for passkey users. It can be implemented using the following authentication actions. The example deployment includes some working actions to compare against.

Authentication SelectorRun a Selector action to present the user's authentication choices.
Switch on Authentication MethodRun a Switch action to route the user to an authentication or action.
Check if User ExistsRun a Data Source Transformer action to see if the user exists.
Registration FormRun an Attribute Prompt action for new users who want to login with passkeys.
Activate UserRun a Script Transformer action to set the user to an active state.
Create AccountUse an Auto Create Account action to save the user account details after registration.

Using Passkeys

Once the user creates an account for the passkey option, they next need to perform the passkey registration ceremony. In the example flow, you first ask the user to verify their email and the login screen will poll for completion. The user can then simply switch to their email inbox and click the email link to authenticate:

Email Verification

Next, the user simply follows the system dialogs to register a passkey and authenticate with it. All future user logins are then simple from a usability viewpoint. The user then provides a second factor to prove their presence, such as by entering the device PIN or providing a fingerprint biometric.

Simple registration prompt
Simple authenticate prompt

Passkeys Account Recovery

Users often access the same application across different browsers and devices. In some cases, passkeys can synchronize, yet you cannot always rely upon this. The Passkeys - Design your Solution article explains the current technology support on various platforms.

When a new browser or device does not support synchronization, the user will not be able to log in with their existing passkey. Yet the user can recover by re-performing the registration ceremony, to create a new passkey for the new browser or device. You can customize user messages for the passkeys authenticator to give the user a hint on how to recover:

Passkeys Recovery Hint

The user then clicks the Register new passkey option and re-runs the registration ceremony. The Curity Identity Server then registers the public key of the new passkey. Note that you can register multiple public keys against each user account. This enables users to recover from any lost passkey scenario.

Removing Password Logins

In some use cases, you may want to customize behavior so that passkey users no longer see password login options. Meanwhile, you encourage password users to upgrade to passkeys whenever they sign in. You can enable this with the same authentication actions, to provide a user routing sequence that sends passkey users directly to the passkeys authenticator:

Example Deployment

You can use the GitHub repository link from the top of this page to run a working setup. The example setup assumes that you use OAuth Tools as a test client that connects to a local Docker-based instance of the Curity Identity Server using ngrok. You will also need a license file for the Curity Identity Server with support for passkeys, such as a trial license. Copy this into the repo's root folder.

Deploy the System

Next, run the following commands to deploy the Curity Identity Server, along with a PostgreSQL database that stores account data and public keys for registered passkeys:

export USE_NGROK=true
./apply-use-case.sh ./config/4-configure-migrating-to-passwordless.xml

The script outputs an OpenID Connect metadata URL similar to this:

The OpenID Connect Metadata URL is at: https://4099-2-26-218-80.eu.ngrok.io/oauth/v2/oauth-anonymous/.well-known/openid-configuration

In OAuth Tools, create a new workspace and paste this URL into the Metadata URL field:

OAuth Tools Environment

You will then need to run a code flow in OAuth Tools with the following settings:

Client ID: demo-web-client
Client Secret: Password1
Scope: openid

Note that redeploying the containers clears user accounts, so that you can test onboarding and subsequent logins, for both password and passkey users.

Test User Flows

Use the example deployment to test various scenarios including those listed below. These will enable you to review both the user experience and account recovery behaviors:

Test ActionExpected Outcome
Create a new user with password logins.The user creates an account and can log in with a password credential.
Upgrade the user to use passkey logins.After registering a passkey the user no longer sees a password login option.
Create a new user with passkey logins.The user creates an account, registers a passkey and only ever signs in with passkeys.
Delete the passkey from the browser.The user can register a new passkey and recover.
Switch to a different browserRe-run OAuth Tools in another browser and register a new passkey if required.

The example deployment includes an instance of the Maildev SMTP Server that you can use to test email verification when registering or re-registering passkeys. To do so, browse to http://localhost:8080 and click the Authenticate option in any e-mail that you receive:

Email Recovery

Example Actions

Follow the instructions in the GitHub repo's README file to log into the admin UI and view authentication actions. These include the passkeys registration sequence and user routing sequence that tutorial describes. You can study them and integrate into your instances of the Curity Identity Server.

Example Actions

Account Storage

You can query the account data for your test users from the PostrgreSQL database using these connection details:

Host: localhost
Port: 5432
User: postgres
Password: Password1
Database: idsvr

Alternatively, you can use the shell to query the database. Enter the following commands to first connect to the PostgreSQL container:

CONTAINER_ID=$(docker ps | grep postgres | awk '{print $1}')
docker exec -it $CONTAINER_ID bash
export PGPASSWORD=Password1 && psql -p 5432 -d idsvr -U postgres

Then, select the created user accounts and their registered public keys:

select * from accounts;
select * from devices;

You will see that upgrading from passwords to passkeys reuses the existing account. When the Curity Identity Server issues access tokens to clients, they will have the same user identity and claims as they had previously. Therefore, upgrading to passkeys will not have any adverse effects on your APIs.


When rolling out passkey logins you must think through the different user types, to enable your preferred user behaviors. Choose a registration authenticator that the user can re-use to create multiple passkeys when required. By following the steps in this tutorial you will be able to gradually phase out passwords, to improve security while also enabling a modern user experience.

Join our Newsletter

Get the latest on identity management, API Security and authentication straight to your inbox.

Start Free Trial

Try the Curity Identity Server for Free. Get up and running in 10 minutes.

Start Free Trial