Passkey Login Authentication

If a user has added a passkey to their account, or they initially signed up with a passkey, you can easily authenticate them using that passkey. This provides a secure, passwordless authentication experience.

You can implement Passkey Login authentication in two ways:

Pre-built UI Components

Account Kit provides pre-built UI components that handle the entire Passkey Login 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:

import React from "react";
import { 
const useAuthModal: () => { isOpen: boolean; openAuthModal: () => void; closeAuthModal: () => void; }

A hook that returns the open and close functions for the Auth Modal if uiConfig is enabled on the Account Provider

useAuthModal
} from "@account-kit/react";
export default function
function MyPage(): JSX.Element
MyPage
() {
const {
const openAuthModal: () => void
openAuthModal
} =
function useAuthModal(): { isOpen: boolean; openAuthModal: () => void; closeAuthModal: () => void; }

A hook that returns the open and close functions for the Auth Modal if uiConfig is enabled on the Account Provider

useAuthModal
();
return <
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={
const openAuthModal: () => void
openAuthModal
}>Sign in</
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
>;
}

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

Or:

Using Embedded Authentication

To embed authentication directly in your page:

import React from "react";
import { 
const AuthCard: (props: AuthCardProps) => JSX.Element

React component containing an Auth view with configured auth methods and options based on the config passed to the AlchemyAccountProvider

AuthCard
} from "@account-kit/react";
export default function
function MyLoginPage(): JSX.Element
MyLoginPage
() {
return ( <
React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
React.HTMLAttributes<HTMLDivElement>.className?: string | undefined
className
="flex flex-row p-4 bg-white border border-gray-200 rounded-lg">
<
const AuthCard: (props: AuthCardProps) => JSX.Element

React component containing an Auth view with configured auth methods and options based on the config passed to the AlchemyAccountProvider

AuthCard
/>
</
React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
); }

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

Step 2: Configure Passkey Login in UI Components

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

To customize the Passkey Login authentication experience in your pre-built components, configure the UI as follows:

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 login in a section
9 { type: "passkey" },
10
11 // You can combine with other authentication methods
12 { type: "email" },
13 ],
14 ],
15 },
16};
17
18export const config = createConfig(
19 {
20 transport: alchemy({ apiKey: "your-api-key" }),
21 chain: sepolia,
22 },
23 uiConfig,
24);

Passkey login configuration accepts the following options:

type 
type PasskeyAuthType = { type: "passkey"; }
PasskeyAuthType
= {
type: "passkey"
type
: "passkey";
};

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

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 Login authentication using Account Kit hooks.

Option 1: Passkey Login with Email

If the user’s passkey is associated with an email, you can use the email to help identify the correct passkey:

1import { useAuthenticate } from "@account-kit/react";
2
3// Inside your component
4const { authenticate } = useAuthenticate();
5
6// When the user wants to log in with their passkey and email
7const handlePasskeyLogin = (email: string) => {
8 authenticate(
9 {
10 type: "passkey",
11 email,
12 },
13 {
14 onSuccess: () => {
15 // Success - user authenticated with passkey
16 },
17 onError: (error) => {
18 // Handle error
19 },
20 },
21 );
22};

Option 2: Passkey Login without Email

If you want to authenticate a user with just their passkey (without requiring an email), you can use this approach:

1import { useAuthenticate } from "@account-kit/react";
2
3// Inside your component
4const { authenticate } = useAuthenticate();
5
6// When the user wants to log in with just their passkey
7const handlePasskeyOnlyLogin = () => {
8 authenticate(
9 {
10 type: "passkey",
11 createNew: false, // Important: set to false to prevent creating a new passkey
12 },
13 {
14 onSuccess: () => {
15 // Success - user authenticated with passkey
16 },
17 onError: (error) => {
18 // Handle error
19 },
20 },
21 );
22};

Step 3: Track Authentication Status

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

import { 
const useSignerStatus: (override?: AlchemyAccountContextProps) => UseSignerStatusResult

Hook to get the signer status, optionally using an override configuration, useful if you’re building your own login.

useSignerStatus
} from "@account-kit/react";
// Inside your component const {
const isConnected: boolean
isConnected
} =
function useSignerStatus(override?: AlchemyAccountContextProps): UseSignerStatusResult

Hook to get the signer status, optionally using an override configuration, useful if you’re building your own login.

useSignerStatus
();
// You can use isConnected to conditionally render UI