Skip to content

title: Authenticating Users via One-Time Password (OTP) description: Learn how to authenticate users via a one-time password (OTP), sent to their email


Authenticating Users via OTP

Authenticating a user is easy using the useAuthenticate() hook from the @account-kit/react-native package.

Set the Email Mode to One Time Password (OTP) in your Account Kit Dashboard

In your Alchemy Accounts Dashboard:

  • Navigate to the Smart Wallets tab

  • Select the config you would be using for your project and click the Edit button

  • Scroll down to the Email Mode options in the Email section and select One Time Password (OTP)

    Email Mode OTP
  • Click the Save Changes button

Send a One-Time Password (OTP) to a User

To send an OTP to a user's email, use the authenticate() function from the useAuthenticate() hook with the type set to email and the emailMode set to otp.

sign-in-with-otp.tsx
import { useAuthenticate } from "@account-kit/react-native";
import React, { useState } from "react";
import { Alert, View, Text, TextInput, Button, Pressable } from "react-native";
 
function SignInWithOtp() {
  const { authenticate } = useAuthenticate();
  const [email, setEmail] = useState("");
 
  const handleUserSignInWithOtp = () => {
    try {
      authenticate({
        email,
        type: "email",
      });
 
      // OTP sent to the user's email. Prompt the user to enter the OTP into your app.
    } catch (e) {
      Alert.alert("Error sending OTP Code. Check logs for more details.");
 
      console.log("Error seding OTP CODE: ", e);
    }
  };
 
  return (
    <View>
      <Text>Enter Your Email to Sign In</Text>
      <View>
        <TextInput
          value={email}
          onChangeText={(val) => setEmail(val.toLowerCase())}
          placeholder="john@doe.com"
        />
        <Pressable onPress={handleUserSignInWithOtp}>
          {({ pressed }) => (
            <View
              style={[
                {
                  opacity: pressed ? 0.5 : 1,
                  transform: [
                    {
                      scale: pressed ? 0.98 : 1,
                    },
                  ],
                },
              ]}
            >
              <Text>Sign In</Text>
            </View>
          )}
        </Pressable>
      </View>
    </View>
  );
}

Prompt the User to enter the One-Time Password to complete authentication

The user will receive an email with a one-time password (OTP) to enter into your app.

Provide a means for the user to enter the OTP into your app and then call the authenticate() function from the useAuthenticate() hook passing the OTP code to the otpCode parameter, and the type set to otp.

verify-otp.tsx
import { useAuthenticate } from "@account-kit/react-native";
import React, { useState } from "react";
import { Alert, View, Text, TextInput, Button, Pressable } from "react-native";
 
function VerifyOtp() {
  const { authenticate } = useAuthenticate();
  const [otpCode, setOtpCode] = useState("");
 
  const handleUserVerifyOtp = () => {
    try {
      authenticate({
        otpCode,
        type: "otp",
      });
 
      // OTP verified. User is authenticated.
    } catch (e) {
      Alert.alert("Error verifying OTP Code. Check logs for more details.");
 
      console.log("Error verifying OTP CODE: ", e);
    }
  };
 
  return (
    <View>
      <View>
        <Text>Enter Your OTP Code</Text>
        <View>
          <TextInput
            value={otpCode}
            onChangeText={setOtpCode}
            placeholder="123456"
          />
          <Pressable onPress={handleUserVerifyOtp}>
            {({ pressed }) => (
              <View
                style={[
                  {
                    opacity: pressed ? 0.5 : 1,
                    transform: [
                      {
                        scale: pressed ? 0.98 : 1,
                      },
                    ],
                  },
                ]}
              >
                <Text>Submit OTP</Text>
              </View>
            )}
          </Pressable>
        </View>
      </View>
    </View>
  );
}

Here's an example of a Sign In component using OTP. Feel free to embed this into your application to give it a try!

sign-in-with-otp.tsx
import React, { useCallback, useState } from "react";
import { View, Text, TextInput, Button } from "react-native";
import { useAuthenticate, useUser } from "@account-kit/react-native";
 
import { OtpPopUp } from "./otp-popup";
 
export const SignInWithOtp = () => {
  const [email, setEmail] = useState<string>("");
  const [showOtp, setShowOtp] = useState<boolean>(false);
 
  const [loading, setLoading] = useState<boolean>(false);
  const { authenticate } = useAuthenticate();
  const { user } = useUser();
 
  // Make an authentication request to a user's email
  const performAuthRequest = useCallback(
    (email: string) => {
      try {
        authenticate({
          email,
          type: "email",
          emailMode: "otp",
        });
 
        setLoading(true);
        setShowOtp(true);
      } catch (e) {
        Alert.alert("Error sending OTP Code. Check logs for more details.");
 
        console.log("Error seding OTP CODE: ", e);
      }
    },
    [authenticate]
  );
 
  const completeAuth = useCallback(() => {
    setLoading(false);
    setShowOtp(false);
  }, []);
 
  return (
    <View>
      {user && (
        <>
          <Text>User Authenticated As: {user.email}</Text>
          <Text>{user.address}</Text>
        </>
      )}
 
      <Text style={{ fontSize: 16 }}>Enter Email</Text>
      <TextInput
        value={email}
        style={{ fontSize: 20 }}
        onChangeText={setEmail}
        placeholder="Enter Email"
        autoCapitalize="none"
      />
      <Button
        title={loading ? "Loading" : "Sign In"}
        disabled={loading}
        onPress={() => performAuthRequest(email)}
      />
 
      <OtpPopUp
        show={showOtp}
        completeAuth={completeAuth}
        close={() => {
          setShowOtp(false);
          setLoading(false);
        }}
      />
    </View>
  );
};