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

# Passkeys

Passkeys use cryptographic key pairs stored on the user's device. Authentication happens with a biometric check (such as Face ID, Touch ID, or a fingerprint scan)
or a local device PIN. This makes passkeys both safer—since they can't be phished or reused—and easier to use, since users don't need to remember or type credentials.

## Prerequisites

* You need to have the Dynamic Client initialized.
* You need to have the passkey MFA enabled in your environment's settings in the [Dynamic dashboard](https://app.dynamic.xyz/dashboard/security).

## Registering a new passkey

Calling `registerPasskey` will prompt the user to register a new passkey in their device and register it in the Dynamic server,
so next time the user can complete an MFA challenge with it or even [sign-in with it](/javascript/authentication-methods/passkey) if enabled in the environment's settings.

Registering a passkey will automatically authenticate it, so you don't need to call `authenticatePasskeyMFA` after registering a passkey.

```javascript theme={"system"}
import { registerPasskey } from '@dynamic-labs-sdk/client';

const register = async () => {
  await registerPasskey();
};

```

## Doing MFA authentication with a passkey

Calling `authenticatePasskeyMFA` will prompt the user to authenticate with a passkey in their device and complete an MFA challenge.
The authentication will be successful if the user authenticates with the passkey in their device and it gets validated in the Dynamic server.

```javascript theme={"system"}
import { authenticatePasskeyMFA } from '@dynamic-labs-sdk/client';

const onLogin = async () => {
  await authenticatePasskeyMFA();
};
```

### With step-up authentication (recommended)

Pass `requestedScopes` to receive an [elevated access token](/overview/authentication/step-up-auth) for sensitive actions:

```javascript theme={"system"}
import { authenticatePasskeyMFA } from '@dynamic-labs-sdk/client';

const onExportPrivateKeyClick = async () => {
  await authenticatePasskeyMFA({
    requestedScopes: ['wallet:export'],
  });

  // Elevated token is now stored — the SDK attaches it automatically
  await exportWaasPrivateKey(params);
};
```

### With MFA token (deprecated)

<Warning>
  `createMfaToken` is deprecated and will be removed in the next major version. Use `requestedScopes` instead. See [migration guide](/overview/authentication/step-up-auth#migration-from-mfa-tokens).
</Warning>

```javascript theme={"system"}
import { authenticatePasskeyMFA } from '@dynamic-labs-sdk/client';

const onExportPrivateKeyClick = async () => {
  await authenticatePasskeyMFA({
    createMfaToken: { singleUse: true },
  });

  await exportWaasPrivateKey(params);
};
```

## Deleting a passkey

Calling `deletePasskey` will delete a passkey from the Dynamic server.

```javascript theme={"system"}
import { deletePasskey } from '@dynamic-labs-sdk/client';

const delete = async () => {
  // Replace 'passkey-id' with the actual ID of the passkey you want to delete
  await deletePasskey({passkeyId: 'passkey-id'});
};

```

## Getting all registered passkeys for a user

Calling `getPasskeys` will return all registered passkeys for the authenticated user.

```javascript theme={"system"}
import { getPasskeys } from '@dynamic-labs-sdk/client';

const getUserPasskeys = async () => {
  const passkeys = await getPasskeys();
  console.log(passkeys);
};

```

## React

`useGetPasskeys` fetches the list. Mutations like `useRegisterPasskey` and `useDeletePasskey` automatically refetch the passkey list on success, so the UI stays in sync without manual intervention:

```tsx theme={"system"}
import {
  useAuthenticatePasskeyMFA,
  useDeletePasskey,
  useGetPasskeys,
  useRegisterPasskey,
} from '@dynamic-labs-sdk/react-hooks';

function PasskeyManager() {
  const { data: passkeys = [] } = useGetPasskeys();
  const { mutate: registerPasskey } = useRegisterPasskey();
  const { mutate: deletePasskey } = useDeletePasskey();

  return (
    <div>
      <button onClick={() => registerPasskey()}>Register New Passkey</button>
      <ul>
        {passkeys.map((p) => (
          <li key={p.id}>
            {p.name ?? p.id}
            <button onClick={() => deletePasskey({ passkeyId: p.id })}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

function PasskeyMfaButton() {
  const { mutate: authenticatePasskeyMFA } = useAuthenticatePasskeyMFA();

  return (
    <button onClick={() => authenticatePasskeyMFA({ requestedScopes: ['wallet:export'] })}>
      Authenticate with Passkey
    </button>
  );
}
```

## Related functions

* [Step-Up Authentication](/javascript/authentication-methods/step-up-auth/overview)
* [Signing in with a Passkey](/javascript/authentication-methods/passkey)
* [Authenticator Apps](/javascript/authentication-methods/mfa/totp)
* [Recovery Codes](/javascript/authentication-methods/mfa/recovery-codes)
* [Overview](/javascript/authentication-methods/mfa/overview)
* [Session-Based MFA](/javascript/authentication-methods/mfa/session-mfa)
* [Action-Based MFA](/javascript/authentication-methods/mfa/action-based)
