> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dfns.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Register passkeys on a new domain

> How to let users register new passkey credentials when your frontend moves to a different domain, while preserving access to existing wallets.

Passkeys are cryptographically bound to the domain (rpId) where they were created. When you move your frontend to a new domain, existing passkeys stop working. Users must register new credentials on the new domain.

The [Create Credential With Code](/api-reference/auth/credentials#create-credential-with-code-flow) flow solves this: the user signs in on the old domain (where their passkey works), gets a one-time code, and uses it to register a new passkey on the new domain.

## Prerequisites

* **Whitelist the new domain** in Dashboard > Settings > Passkeys before starting. See [Dashboard configuration](/guides/developers/webauthn-configuration#dashboard-configuration).
* **Keep the old domain accessible** during the transition. Users need to sign with their existing passkey to initiate the flow.
* **SDK v0.6.0+** for explicit rpId support.

## Migration flow

<Steps>
  <Step title="Generate a credential code on the old domain">
    The user signs in on the old domain and triggers credential migration. Your backend calls [Create Credential Code](/api-reference/auth/create-credential-code). This requires a [user action signature](/api-reference/auth/signing-flows) with the user's existing passkey.

    The API returns a 9-character one-time code, valid for 1 minute.
  </Step>

  <Step title="Transfer the code to the new domain">
    Pass the code to your new domain. How you do this is up to you: redirect with query parameter, QR code, manual entry, or any other method that fits your UX.
  </Step>

  <Step title="Get a credential challenge on the new domain">
    On the new domain, call [Create Credential Challenge With Code](/api-reference/auth/create-credential-challenge-with-code), passing the code from step 1. This returns a registration challenge. No existing credential signature is needed.
  </Step>

  <Step title="Create the new passkey">
    Use the challenge to create a new passkey via WebAuthn. The new passkey will be bound to the new domain's rpId.

    ```typescript title="New domain frontend" theme={null}
    import { WebAuthn } from '@dfns/sdk-browser'

    const webauthn = new WebAuthn({
      rpId: 'new-domain.com',
    })

    const attestation = await webauthn.create(challenge)
    ```
  </Step>

  <Step title="Complete registration">
    Call [Create Credential With Code](/api-reference/auth/create-credential-with-code), passing the attestation and the code. No user action signature is required for this call.

    The user now has a passkey that works on the new domain.
  </Step>
</Steps>

## After migration

Once your users have re-registered on the new domain, you can optionally [deactivate](/api-reference/auth/deactivate-credential) their old credentials tied to the previous domain. Keep the old domain live until you're confident all active users have migrated.

<Tip>
  To avoid this problem in the future, use your root domain (e.g., `example.com`) as the rpId instead of a subdomain. Passkeys created with a root domain rpId work on all subdomains. See [rpId rules](/guides/developers/webauthn-configuration#rpid-rules).
</Tip>

## Related

<CardGroup cols={2}>
  <Card title="Configure WebAuthn" icon="gear" href="/guides/developers/webauthn-configuration">
    rpId rules, domain setup, and troubleshooting
  </Card>

  <Card title="Credential With Code flow" icon="key" href="/api-reference/auth/credentials#create-credential-with-code-flow">
    API reference for the full flow
  </Card>

  <Card title="Rotate credentials" icon="rotate" href="/guides/developers/credential-rotation">
    Replacing service account keys, webhook secrets, and user credentials
  </Card>
</CardGroup>
