Passkey Signup Authentication

Passkeys provide a secure, passwordless authentication method that can be used to create wallets for your users without going through email verification flows. You can implement passkey signup with or without an associated email address.

If you create a passkey without an email associated with the user, you risk your users losing access to their wallets if they lose their device.

Recommended security practice: Proxy authentication requests to your backend server to enforce additional security measures:

  • When a user attempts to sign up with both passkey and email, you can first require email verification before allowing the passkey to be created
  • Alternatively, you can restrict initial signup to email-based methods only (which inherently verify email ownership), then allow users to add passkeys after their account is established
  • This approach gives you greater control over the authentication flow and helps prevent account recovery issues

By implementing server-side verification, you ensure that passkeys are only created for verified identities, reducing the risk of permanent access loss.

You can implement Passkey Signup authentication in two ways:

Pre-built UI Components

Account Kit provides pre-built UI components that handle the entire Passkey Signup authentication flow with minimal code.

Step 1: Add Authentication Components to Your Page

Before configuring your authentication, first add one of the pre-built components to your application:

Using Modal Authentication

To add authentication in a modal popup:

1import React from "react";
2import { useAuthModal } from "@account-kit/react";
3
4export default function MyPage() {
5 const { openAuthModal } = useAuthModal();
6
7 return <button onClick={openAuthModal}>Sign in</button>;
8}

For more details on modal configuration, see the Modal Authentication documentation.

Or:

Using Embedded Authentication

To embed authentication directly in your page:

1import React from "react";
2import { AuthCard } from "@account-kit/react";
3
4export default function MyLoginPage() {
5 return (
6 <div className="flex flex-row p-4 bg-white border border-gray-200 rounded-lg">
7 <AuthCard />
8 </div>
9 );
10}

For more details on embedded authentication, see the Embedded Authentication documentation.

Step 2: Configure Passkey Signup in UI Components

After adding the components, configure the Passkey Signup authentication in your application config:

1import { AlchemyAccountsUIConfig, createConfig } from "@account-kit/react";
2import { sepolia, alchemy } from "@account-kit/infra";
3
4const uiConfig: AlchemyAccountsUIConfig = {
5 auth: {
6 sections: [
7 [
8 // Include passkey in a section
9 { type: "passkey" },
10
11 // You can combine with other authentication methods
12 { type: "email" },
13 ],
14 ],
15 // Enable automatic passkey creation after signup
16 addPasskeyOnSignup: true,
17 },
18};
19
20export const config = createConfig(
21 {
22 transport: alchemy({ apiKey: "your-api-key" }),
23 chain: sepolia,
24 },
25 uiConfig
26);

Passkey signup configuration accepts the following options:

1type PasskeyAuthType = {
2 type: "passkey";
3};

You can find the full type definition in the Account Kit source code.

The key configuration option for passkey signup is addPasskeyOnSignup: true, which will prompt users to create a passkey after they sign up with another method (like email).

For more details on UI component customization, see the UI Components documentation.

Custom UI

If you need complete control over the user experience, you can implement your own custom UI for Passkey Signup authentication using Account Kit hooks.

This approach associates an email with the passkey, allowing users to recover their account if they lose access to their device.

1import { useAuthenticate } from "@account-kit/react";
2
3// Inside your component
4const { authenticate } = useAuthenticate();
5
6// When the user submits their email and wants to create a passkey
7const handlePasskeySignup = (email: string) => {
8 // Important: Validate the email before proceeding
9 if (!isValidEmail(email)) {
10 // Handle validation error
11 return;
12 }
13
14 authenticate(
15 {
16 type: "passkey",
17 email,
18 },
19 {
20 onSuccess: () => {
21 // Success - passkey created and user authenticated
22 },
23 onError: (error) => {
24 // Handle error
25 },
26 }
27 );
28};
29
30// Simple email validation function
31const isValidEmail = (email: string) => {
32 return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
33};

It’s important that you validate the email before creating an account for the user. This is to prevent users from losing access to their wallets if they lose their device.

Option 2: Passkey Signup without Email

This approach creates a passkey without an associated email. Use this only if you have another recovery mechanism in place.

1import { useAuthenticate } from "@account-kit/react";
2
3// Inside your component
4const { authenticate } = useAuthenticate();
5
6// When the user wants to create a passkey without email
7const handlePasskeyOnlySignup = (username: string) => {
8 authenticate(
9 {
10 type: "passkey",
11 createNew: true,
12 username, // A unique identifier for the passkey
13 },
14 {
15 onSuccess: () => {
16 // Success - passkey created and user authenticated
17 },
18 onError: (error) => {
19 // Handle error
20 },
21 }
22 );
23};

Step 3: Track Authentication Status

Use the useSignerStatus hook to determine if the user is authenticated:

1import { useSignerStatus } from "@account-kit/react";
2
3// Inside your component
4const { isConnected } = useSignerStatus();
5
6// You can use isConnected to conditionally render UI