Skip to content

Email OTP Authentication

Email OTP (One-Time Password) authentication is a two-step process:

  1. The user enters their email address and requests a verification code
  2. The user enters the 6-digit code they receive in their inbox to complete authentication

You can implement Email OTP authentication in two ways:

Pre-built UI Components

Account Kit provides pre-built UI components that handle the entire Email OTP 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 { useAuthModal } from "@account-kit/react";
 
export default function MyPage() {
  const { openAuthModal } = useAuthModal();
 
  return <button onClick={openAuthModal}>Sign in</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 { AuthCard } from "@account-kit/react";
 
export default function MyLoginPage() {
  return (
    <div className="flex flex-row p-4 bg-white border border-gray-200 rounded-lg">
      <AuthCard />
    </div>
  );
}

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

Step 2: Configure Email OTP in UI Components

After adding the components, configure the Email OTP authentication in your application config:

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

import { AlchemyAccountsUIConfig, createConfig } from "@account-kit/react";
import { sepolia, alchemy } from "@account-kit/infra";
 
const uiConfig: AlchemyAccountsUIConfig = {
  auth: {
    sections: [
      [
        {
          type: "email",
          emailMode: "otp",
 
          // Optional customizations:
          buttonLabel: "Continue with Email",
          placeholder: "Enter your email address",
        },
      ],
    ],
  },
};
 
export const config = createConfig(
  {
    transport: alchemy({ apiKey: "your-api-key" }),
    chain: sepolia,
  },
  uiConfig
);

Email OTP configuration accepts the following options:

type EmailAuthType = {
  type: "email";
  emailMode: "otp";
  // hides the continue button
  hideButton?: boolean;
  // changes the button label
  buttonLabel?: string;
  // changes the placeholder text in the input
  placeholder?: string;
};

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

Step 1: Send the OTP

First, prompt your user for their email address and send an OTP:

import { useAuthenticate } from "@account-kit/react";
 
// Inside your component
const { authenticate } = useAuthenticate();
 
// When the user submits their email
const handleSendCode = (email: string) => {
  authenticate(
    {
      type: "email",
      emailMode: "otp",
      email,
    },
    {
      onSuccess: () => {
        // Success - now show the OTP input form
      },
      onError: (error) => {
        // Handle error
      },
    }
  );
};

Step 2: Verify the OTP

Once the user receives the code, they'll enter it in your application:

import { useAuthenticate } from "@account-kit/react";
 
// Inside your component
const { authenticate } = useAuthenticate();
 
// When the user submits the OTP code
const handleVerifyCode = (otpCode: string) => {
  authenticate(
    {
      type: "otp",
      otpCode,
    },
    {
      onSuccess: () => {
        // Authentication successful!
      },
      onError: (error) => {
        // Handle invalid code error
      },
    }
  );
};

Step 3: Track Authentication Status

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

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