Email Magic Link Authentication

Email magic link authentication is a two-step process:

  1. The user enters their email address and requests a magic link
  2. The user clicks the link in their email, which redirects them back to your application to complete authentication

Email OTP has been shown to have up to a 3x higher conversion rate and a 10-second faster flow compared to magic links. Consider using Email OTP for better user experience.

You can implement Email Magic Link authentication in two ways:

Pre-built UI Components

Account Kit provides pre-built UI components that handle the entire Email Magic Link 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.

After adding the components, configure the Email Magic Link 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 {
9 type: "email",
10 emailMode: "magicLink",
11
12 // Optional customizations:
13 buttonLabel: "Continue with Email",
14 placeholder: "Enter your email address",
15 },
16 ],
17 ],
18 },
19};
20
21export const config = createConfig(
22 {
23 transport: alchemy({ apiKey: "your-api-key" }),
24 chain: sepolia,
25 },
26 uiConfig
27);

Email Magic Link configuration accepts the following options:

1type EmailAuthType = {
2 type: "email";
3 emailMode: "magicLink";
4 // hides the continue button
5 hideButton?: boolean;
6 // changes the button label
7 buttonLabel?: string;
8 // changes the placeholder text in the input
9 placeholder?: string;
10};

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

First, prompt your user for their email address and send a magic link:

1import { useAuthenticate } from "@account-kit/react";
2
3// Inside your component
4const { authenticate } = useAuthenticate();
5
6// When the user submits their email
7const handleSendMagicLink = (email: string) => {
8 authenticate(
9 {
10 type: "email",
11 emailMode: "magicLink",
12 email,
13 },
14 {
15 onSuccess: () => {
16 // onSuccess only fires once the entire flow is done (email magic link + optional MFA).
17 // It still runs even if the final step completes in another tab/window.
18 },
19 onError: (error) => {
20 // Handle error
21 },
22 }
23 );
24};

Step 2: Handle the Redirect

When the user clicks the magic link in their email, they’ll be redirected back to your application. You need to extract the authentication bundle from the URL and complete the authentication:

1import { useEffect } from "react";
2import { useAuthenticate } from "@account-kit/react";
3
4// Inside your component
5const { authenticate } = useAuthenticate();
6
7// Handle the redirect when the component mounts
8useEffect(() => {
9 const handleRedirect = () => {
10 const url = new URL(window.location.href);
11 const bundle = url.searchParams.get("bundle");
12
13 if (bundle) {
14 authenticate(
15 {
16 type: "email",
17 bundle,
18 },
19 {
20 onSuccess: () => {
21 // onSuccess only fires once the entire flow is done (email magic link + optional MFA).
22 // It still runs even if the final step completes in another tab/window.
23 },
24 onError: (error) => {
25 // Handle error
26 },
27 }
28 );
29 }
30 };
31
32 handleRedirect();
33}, [authenticate]);

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

Next Steps

Add Authenticator App (TOTP) Verification (Optional)

Consider enabling Multi-Factor Authentication to require users to enter a 6-digit TOTP code from their authenticator app after clicking the magic link. This extra layer of security protects user accounts if their email is compromised.