# Passkey Authentication (/wallets/auth/passkeys)

> For the complete documentation index, see [llms.txt](/llms.txt)



Passkeys are the fastest passwordless option for most apps. Users authenticate with Face ID, Touch ID, a fingerprint, a device PIN, or a hardware security key.

Use passkeys when you want an email-free wallet flow. Passkeys use [WebAuthn](https://webauthn.guide/), and the browser handles the passkey prompt.

## Configure Wagmi [#configure-wagmi]

Passkeys work with the same connector setup from the [Quickstart](/wallets/quickstart):

```tsx
import { zeroDevWallet } from '@zerodev/wallet-react'
import { createConfig, http } from 'wagmi'
import { arbitrumSepolia } from 'wagmi/chains'

const projectId = '<your-project-id>'
const aaHost = 'https://rpc.zerodev.app'
const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc'

export const config = createConfig({
  chains: [arbitrumSepolia],
  connectors: [
    zeroDevWallet({
      projectId,
      aaHost,
      chains: [arbitrumSepolia],
      mode: '7702',
    }),
  ],
  transports: {
    [arbitrumSepolia.id]: http(chainRpcUrl),
  },
})
```

## Set a custom RP ID [#set-a-custom-rp-id]

The relying party ID, or RP ID, is the domain WebAuthn uses to scope a passkey. A passkey registered for one RP ID can only be used later with that same RP ID.

By default, the SDK uses the current hostname. Set `rpId` when you want passkeys to work across subdomains of the same site.

```tsx
zeroDevWallet({
  projectId,
  aaHost,
  chains: [arbitrumSepolia],
  rpId: 'example.com',
})
```

Use a domain only. Do not include a protocol, path, or port. For example, if your app runs on `https://app.example.com` and you want passkeys to work across your app's subdomains, use `example.com`.

Choose the RP ID before users register passkeys. You cannot transfer an existing passkey from one RP ID to another; changing the RP ID later usually means users must register new passkeys.

Learn more in the [WebAuthn RP ID docs](https://www.w3.org/TR/webauthn-3/#rp-id).

## Add passkey login [#add-passkey-login]

Use `useRegisterPasskey` for new users and `useLoginPasskey` for returning users.

Registration creates a new passkey. Login asks the user to choose an existing passkey and approve the browser prompt. In Chrome, for example, that prompt may use the OS password manager, device biometrics, a PIN, or a hardware security key.

```tsx
import { useLoginPasskey, useRegisterPasskey } from '@zerodev/wallet-react'
import { useAccount, useDisconnect } from 'wagmi'

export function PasskeyLogin() {
  const { address, isConnected } = useAccount()
  const { disconnect } = useDisconnect()
  const registerPasskey = useRegisterPasskey()
  const loginPasskey = useLoginPasskey()

  if (isConnected) {
    return (
      <div>
        <p>Connected: {address}</p>
        <button type="button" onClick={() => disconnect()}>
          Disconnect
        </button>
      </div>
    )
  }

  return (
    <div>
      <button
        type="button"
        disabled={registerPasskey.isPending}
        onClick={() => registerPasskey.mutate()}
      >
        {registerPasskey.isPending ? 'Registering...' : 'Register passkey'}
      </button>

      <button
        type="button"
        disabled={loginPasskey.isPending}
        onClick={() => loginPasskey.mutate()}
      >
        {loginPasskey.isPending ? 'Logging in...' : 'Login with passkey'}
      </button>

      {registerPasskey.error ? <p>{registerPasskey.error.message}</p> : null}
      {loginPasskey.error ? <p>{loginPasskey.error.message}</p> : null}
    </div>
  )
}
```

## How it works [#how-it-works]

1. `useRegisterPasskey` opens the browser's WebAuthn prompt and creates a wallet linked to the new passkey.
2. `useLoginPasskey` opens the WebAuthn prompt and authenticates an existing passkey.
3. After either flow succeeds, the SDK creates a session and connects the ZeroDev Wagmi connector.

Use `useAccount`, `useSignMessage`, and `useSendTransaction` after authentication.

## Notes [#notes]

* Passkeys require a secure context. `localhost` works for local development; production apps should use HTTPS.
* The dashboard ACL allowlist must include the exact origin you open in the browser.
* Passkeys can sync across devices through platform password managers, depending on the user's device, browser, and account recovery settings.

## Next steps [#next-steps]

* [Send a transaction](/wallets/wallet-api/send-transaction)
* [Sign a message](/wallets/wallet-api/sign-message)
* Integrate other login methods: [Email OTP](/wallets/auth/email-otp), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth)
