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

# Email OTP

The Email OTP screen is displayed when users authenticate via email. It prompts users to enter the one-time passcode (OTP) sent to their email address.

<Info>
  The Email OTP screen automatically appears after a user enters their email address in the [login modal](/authentication/user-authentication/ui-components/login).
</Info>

## How it works

When a user selects email authentication:

1. User enters their email address in the login modal
2. MoonKey sends a one-time passcode to the email
3. The Email OTP screen appears, prompting the user to enter the code
4. User enters the 6-digit code
5. Upon successful verification, the user is authenticated

## Customizing the Email OTP screen

You can customize the Email OTP experience by configuring the `emailOtp` prop in your `MoonKeyProvider`:

```tsx theme={null}
import { MoonKeyProvider } from '@moon-key/react-auth';

export default function App() {
  return (
    <MoonKeyProvider
      publishableKey="your_publishable_key"
      config={{
        loginMethods: ['email'],
        emailOtp: {
          skipVerifiedSuccess: false,
          expiresIn: 600,
          verifiedDisplayTime: 3000,
          verifyEmailTitle: 'Verify your email',
          verifyEmailResendTitle: 'Didn\'t receive a code?',
          resendCodeTime: 30,
          verifiedNewUserMessage: 'Email verified! Setting up your account...',
          verifiedExistingUserMessage: 'Welcome back! Signing you in...',
          verifiedSuccessMessage: 'Success! You are now signed in.'
        },
        appearance: {
          logo: 'https://your-app.com/logo.png',
          loginHeaderTitle: 'Welcome',
          loginHeaderDescription: 'Check your email for the verification code'
        }
      }}
    >
      {/* Your app */}
    </MoonKeyProvider>
  );
}
```

## Configuration options

### Email OTP behavior

<ParamField path="skipVerifiedSuccess" type="boolean" default={false}>
  Skip showing the success screen after email verification and immediately proceed to the application.

  When `true`, users won't see a success message and will be taken directly to your app after entering the correct OTP.

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    skipVerifiedSuccess: true // Skip success screen, authenticate immediately
  }
  ```
</ParamField>

<ParamField path="expiresIn" type="number" default={600}>
  Time in seconds before the OTP expires.

  **Default:** `600` (10 minutes)

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    expiresIn: 300 // OTP expires after 5 minutes
  }
  ```
</ParamField>

<ParamField path="verifiedDisplayTime" type="number" default={3000}>
  Time in milliseconds to display the success message before closing the modal.

  Only applies when `skipVerifiedSuccess` is `false`.

  **Default:** `3000` (3 seconds)

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    verifiedDisplayTime: 2000 // Show success message for 2 seconds
  }
  ```
</ParamField>

<ParamField path="resendCodeTime" type="number" default={30}>
  Time in seconds before users can request a new OTP code.

  **Default:** `30` (30 seconds)

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    resendCodeTime: 60 // Users must wait 60 seconds before resending
  }
  ```
</ParamField>

### UI customization

<ParamField path="verifyEmailTitle" type="string" default="Verify your email">
  Title text displayed on the email verification screen.

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    verifyEmailTitle: 'Check your email'
  }
  ```
</ParamField>

<ParamField path="verifyEmailResendTitle" type="string" default="Didn't receive a code?">
  Title text for the resend code prompt.

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    verifyEmailResendTitle: 'Need a new code?'
  }
  ```
</ParamField>

<ParamField path="verifiedNewUserMessage" type="string" default="Email verified!">
  Success message shown to new users after verification.

  Displayed when a user successfully verifies their email for the first time.

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    verifiedNewUserMessage: 'Account created successfully! Welcome aboard.'
  }
  ```
</ParamField>

<ParamField path="verifiedExistingUserMessage" type="string" default="Welcome back!">
  Success message shown to existing users after verification.

  Displayed when a returning user successfully verifies their email.

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    verifiedExistingUserMessage: 'Great to see you again! Signing you in...'
  }
  ```
</ParamField>

<ParamField path="verifiedSuccessMessage" type="string" default="Success!">
  Generic success message shown after verification.

  This is a fallback message when MoonKey cannot determine if the user is new or existing.

  **Example:**

  ```tsx theme={null}
  emailOtp: {
    verifiedSuccessMessage: 'Verification complete!'
  }
  ```
</ParamField>

## Common configurations

### Quick verification (skip success screen)

For a streamlined experience, skip the success screen and authenticate users immediately:

```tsx theme={null}
<MoonKeyProvider
  publishableKey="your_publishable_key"
  config={{
    loginMethods: ['email'],
    emailOtp: {
      skipVerifiedSuccess: true
    }
  }}
>
  {children}
</MoonKeyProvider>
```

### Custom timing

Adjust OTP expiration and resend cooldown for your security requirements:

```tsx theme={null}
<MoonKeyProvider
  publishableKey="your_publishable_key"
  config={{
    loginMethods: ['email'],
    emailOtp: {
      expiresIn: 300, // 5 minutes until expiration
      resendCodeTime: 60, // 60 seconds before allowing resend
      verifiedDisplayTime: 2000 // 2 seconds success message
    }
  }}
>
  {children}
</MoonKeyProvider>
```

### Custom messaging

Personalize the verification flow with custom messages:

```tsx theme={null}
<MoonKeyProvider
  publishableKey="your_publishable_key"
  config={{
    loginMethods: ['email'],
    emailOtp: {
      verifyEmailTitle: 'Enter verification code',
      verifyEmailResendTitle: 'Need a new code?',
      verifiedNewUserMessage: '🎉 Account created! Setting up your wallet...',
      verifiedExistingUserMessage: '👋 Welcome back! Logging you in...',
      verifiedSuccessMessage: '✅ Verified successfully!'
    }
  }}
>
  {children}
</MoonKeyProvider>
```

### Enterprise security settings

For enterprise applications requiring stricter security:

```tsx theme={null}
<MoonKeyProvider
  publishableKey="your_publishable_key"
  config={{
    loginMethods: ['email'],
    emailOtp: {
      expiresIn: 180, // 3 minutes (shorter expiration)
      resendCodeTime: 120, // 2 minutes before resend (prevent spam)
      skipVerifiedSuccess: false, // Show success confirmation
      verifiedDisplayTime: 2000
    }
  }}
>
  {children}
</MoonKeyProvider>
```

## General appearance customization

In addition to Email OTP-specific settings, you can customize the general appearance that applies to all UI components, including the Email OTP screen:

```tsx theme={null}
<MoonKeyProvider
  publishableKey="your_publishable_key"
  config={{
    loginMethods: ['email'],
    emailOtp: {
      verifyEmailTitle: 'Enter your code',
      verifiedNewUserMessage: 'Welcome! Your account is ready.'
    },
    appearance: {
      logo: 'https://your-app.com/logo.png',
      loginHeaderTitle: 'Verify Your Email',
      loginHeaderDescription: 'We sent a 6-digit code to your email',
      hideClose: false
    }
  }}
>
  {children}
</MoonKeyProvider>
```

Learn more about [configuring appearance](/get-started/frontend-sdks/react/advance/configure-appearance).

## Complete example

Here's a complete example with all Email OTP customization options:

```tsx theme={null}
'use client';
import { MoonKeyProvider } from '@moon-key/react-auth';

export default function App() {
  return (
    <MoonKeyProvider
      publishableKey="your_publishable_key"
      config={{
        loginMethods: ['email', 'google'],
        embeddedWallets: {
          createOnLogin: 'always'
        },
        emailOtp: {
          // Behavior
          skipVerifiedSuccess: false,
          expiresIn: 600, // 10 minutes
          verifiedDisplayTime: 3000, // 3 seconds
          resendCodeTime: 30, // 30 seconds
          
          // UI Text
          verifyEmailTitle: 'Check your email',
          verifyEmailResendTitle: 'Didn\'t receive the code?',
          
          // Success messages
          verifiedNewUserMessage: 'Email verified! Setting up your account...',
          verifiedExistingUserMessage: 'Welcome back! Signing you in...',
          verifiedSuccessMessage: 'Success! You are now signed in.'
        },
        appearance: {
          logo: 'https://myapp.com/logo.png',
          loginHeaderTitle: 'Verify Your Email',
          loginHeaderDescription: 'Enter the 6-digit code sent to your email',
          hideClose: false
        }
      }}
    >
      {/* Your app */}
    </MoonKeyProvider>
  );
}
```

## User experience flow

Here's what the complete email authentication flow looks like with Email OTP:

<Steps>
  <Step title="User initiates login">
    User clicks "Sign in" button, opening the login modal.
  </Step>

  <Step title="Enter email address">
    User selects email authentication and enters their email address.
  </Step>

  <Step title="Email OTP screen appears">
    The Email OTP screen appears, prompting the user to enter the code.
  </Step>

  <Step title="Check email">
    User checks their email inbox for the 6-digit verification code.
  </Step>

  <Step title="Enter verification code">
    User enters the code on the Email OTP screen.
  </Step>

  <Step title="Verification & authentication">
    MoonKey verifies the code. If valid:

    * Shows success message (unless `skipVerifiedSuccess: true`)
    * Authenticates the user
    * Creates embedded wallet (if `createOnLogin: 'always'`)
    * Closes the modal and returns user to the app
  </Step>
</Steps>

## Resending codes

If a user doesn't receive the OTP or it expires, they can request a new code:

1. User clicks "Resend code" link on the Email OTP screen
2. MoonKey enforces the `resendCodeTime` cooldown
3. A new OTP is sent to the user's email
4. User enters the new code

The resend cooldown prevents abuse and protects against spam attacks.

## Handling errors

The Email OTP screen automatically handles common errors:

* **Invalid code** - Shows an error message and allows the user to try again
* **Expired code** - Prompts the user to request a new code
* **Too many attempts** - May temporarily lock verification (contact support if this occurs)

## Best practices

<AccordionGroup>
  <Accordion title="Choose appropriate expiration times">
    * **Consumer apps**: 5-10 minutes is typical
    * **Enterprise apps**: 3-5 minutes for higher security
    * Consider your users' email access patterns
  </Accordion>

  <Accordion title="Set reasonable resend cooldowns">
    * **Recommended**: 30-60 seconds
    * Prevents spam while allowing legitimate resend requests
    * Too short: risk of abuse
    * Too long: frustrates users
  </Accordion>

  <Accordion title="Provide clear success messages">
    * Differentiate between new and returning users
    * Use friendly, encouraging language
    * Consider your brand voice
  </Accordion>

  <Accordion title="Consider skipping success screen">
    * For faster authentication, set `skipVerifiedSuccess: true`
    * Best for apps where speed is critical
    * Still provide feedback in your app after authentication
  </Accordion>

  <Accordion title="Test the complete flow">
    * Test with various email providers (Gmail, Outlook, etc.)
    * Check spam folders to ensure delivery
    * Verify timing configurations work as expected
    * Test resend functionality
  </Accordion>
</AccordionGroup>

## TypeScript interface

For TypeScript users, here's the complete `EmailOtpConfig` interface:

```typescript theme={null}
interface EmailOtpConfig {
  skipVerifiedSuccess?: boolean;
  expiresIn?: number;
  verifiedDisplayTime?: number;
  verifyEmailTitle?: string;
  verifyEmailResendTitle?: string;
  resendCodeTime?: number;
  verifiedNewUserMessage?: string;
  verifiedExistingUserMessage?: string;
  verifiedSuccessMessage?: string;
}
```

All fields are optional with sensible defaults.

## Next steps

<CardGroup cols={2}>
  <Card title="Email Authentication" icon="envelope" href="/authentication/user-authentication/authentication-methods/email">
    Learn more about email authentication
  </Card>

  <Card title="Login Modal" icon="arrow-right-to-bracket" href="/authentication/user-authentication/ui-components/login">
    Customize the login modal
  </Card>

  <Card title="Configure Appearance" icon="palette" href="/get-started/frontend-sdks/react/advance/configure-appearance">
    Global appearance settings
  </Card>

  <Card title="UI Components Overview" icon="window-maximize" href="/authentication/user-authentication/ui-components/overview">
    Explore all UI components
  </Card>
</CardGroup>
