How to migrate passkeys from one domain (rpID) to a different domain
Passkeys are resistant to phishing attacks because they’re bound to a specific domain (rpId). This does, however, raise some serious issues:
-
Domain migration - At some point you may need to change your domain. If a passkey is registered to old-domain.com, how will your users sign in on new-domain.com?
-
Related domains - You may operate several domains within a group and want to allow users to share their passkey across those domains.
Fortunately the specifications now support related origin requests, allowing you to accept passkeys registered to other domains.
Related Origin Requests
Section titled “Related Origin Requests”Assume existing passkeys are registered to old-domain.com, but want to use new-domain.com. You have a couple of options:
Use the existing Relying Party ID
Section titled “Use the existing Relying Party ID”The simplest option is to continue using an rpId of old-domain.com, even on new-domain.com:
1. Setup your tenancy
Section titled “1. Setup your tenancy”
Continue to use an rpId of old-domain.com
2. Whitelist the new domain
Section titled “2. Whitelist the new domain”Host a /.well-known/webauthn file at the root of old-domain.com (the rpId domain), whitelisting new-domain.com:
{ "origins": [ "https://old-domain.com", "https://new-domain.com" ]}The trade-offs
Section titled “The trade-offs”This is the simplest approach, for both users and developers. There are some drawbacks:
-
You need to host the webauthn file at old-domain.com indefinitely.
-
Some browsers/devices ignore the Relying Party name and display the rpId to users, so they will see the message “do you want to sign in with your old-domain.com passkey?” or similar.
Migrate to a new rpId
Section titled “Migrate to a new rpId”Alternatively, you can use new-domain.com for new passkeys, while continuing to accept passkeys registered to old-domain.com.
1. Update your tenancy settings
Section titled “1. Update your tenancy settings”
rpId is now new-domain.com, with old-domain.com as a related origin
2. Whitelist the new domain
Section titled “2. Whitelist the new domain”Host a /.well-known/webauthn file at the root of old-domain.com (the rpId domain), whitelisting new-domain.com:
{ "origins": [ "https://old-domain.com", "https://new-domain.com" ]}3. Accept legacy passkeys
Section titled “3. Accept legacy passkeys”By default, the browser/client will present passkeys with an rpId of new-domain.com.
If you need to authenticate old-domain.com passkeys after switching your tenancy rpId to new-domain.com, you currently need to either:
- Keep old-domain.com as the tenancy rpId until migration is complete, or
- Implement a custom WebAuthn flow (instead of
authenticatePasskey) so you can explicitly request options for the legacy rpId.
The trade-offs
Section titled “The trade-offs”This approach allows you to support passkeys registered to an old domain, while also registering passkeys against the new domain.
After a user has authenticated with a “legacy” passkey, you can prompt them to register a new one, using the current domain/rpId. You can even delete the old passkey for them. The downsides are:
-
You need to host the webauthn file at old-domain.com until all users have been migrated.
-
You need to somehow establish whether to request a passkey registered to the old or new rpId. There is currently no means of requesting a passkey from either domain.