Authenticating Users via OTP

This guide assumes you have already followed the Setup Guide and have set up the Alchemy Account Provider using this guide. Please refer to the guides above for more information on how to properly setup your project.

For a complete example of how we can setup a project and use the various available authentication methods, please refer to our quickstart example.

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

This is the default mode for email authentication. Only follow these steps if you had previously set the email mode to Magic Link.

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]
1import { useAuthenticate } from "@account-kit/react-native";
2import React, { useState } from "react";
3import { Alert, View, Text, TextInput, Button, Pressable } from "react-native";
4
5function SignInWithOtp() {
6 const { authenticate } = useAuthenticate();
7 const [email, setEmail] = useState("");
8
9 const handleUserSignInWithOtp = () => {
10 try {
11 authenticate({
12 email,
13 type: "email",
14 });
15
16 // OTP sent to the user's email. Prompt the user to enter the OTP into your app.
17 } catch (e) {
18 Alert.alert("Error sending OTP Code. Check logs for more details.");
19
20 console.log("Error seding OTP CODE: ", e);
21 }
22 };
23
24 return (
25 <View>
26 <Text>Enter Your Email to Sign In</Text>
27 <View>
28 <TextInput
29 value={email}
30 onChangeText={(val) => setEmail(val.toLowerCase())}
31 placeholder="[email protected]"
32 />
33 <Pressable onPress={handleUserSignInWithOtp}>
34 {({ pressed }) => (
35 <View
36 style={[
37 {
38 opacity: pressed ? 0.5 : 1,
39 transform: [
40 {
41 scale: pressed ? 0.98 : 1,
42 },
43 ],
44 },
45 ]}
46 >
47 <Text>Sign In</Text>
48 </View>
49 )}
50 </Pressable>
51 </View>
52 </View>
53 );
54}

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]
1import { useAuthenticate } from "@account-kit/react-native";
2import React, { useState } from "react";
3import { Alert, View, Text, TextInput, Button, Pressable } from "react-native";
4
5function VerifyOtp() {
6 const { authenticate } = useAuthenticate();
7 const [otpCode, setOtpCode] = useState("");
8
9 const handleUserVerifyOtp = () => {
10 try {
11 authenticate({
12 otpCode,
13 type: "otp",
14 });
15
16 // OTP verified. User is authenticated.
17 } catch (e) {
18 Alert.alert("Error verifying OTP Code. Check logs for more details.");
19
20 console.log("Error verifying OTP CODE: ", e);
21 }
22 };
23
24 return (
25 <View>
26 <View>
27 <Text>Enter Your OTP Code</Text>
28 <View>
29 <TextInput
30 value={otpCode}
31 onChangeText={setOtpCode}
32 placeholder="123456"
33 />
34 <Pressable onPress={handleUserVerifyOtp}>
35 {({ pressed }) => (
36 <View
37 style={[
38 {
39 opacity: pressed ? 0.5 : 1,
40 transform: [
41 {
42 scale: pressed ? 0.98 : 1,
43 },
44 ],
45 },
46 ]}
47 >
48 <Text>Submit OTP</Text>
49 </View>
50 )}
51 </Pressable>
52 </View>
53 </View>
54 </View>
55 );
56}

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

1// @noErrors
2import React, { useCallback, useState } from "react";
3import { View, Text, TextInput, Button } from "react-native";
4import { useAuthenticate, useUser } from "@account-kit/react-native";
5
6import { OtpPopUp } from "./otp-popup";
7
8export const SignInWithOtp = () => {
9 const [email, setEmail] = useState<string>("");
10 const [showOtp, setShowOtp] = useState<boolean>(false);
11
12 const [loading, setLoading] = useState<boolean>(false);
13 const { authenticate } = useAuthenticate();
14 const { user } = useUser();
15
16 // Make an authentication request to a user's email
17 const performAuthRequest = useCallback(
18 (email: string) => {
19 try {
20 authenticate({
21 email,
22 type: "email",
23 emailMode: "otp",
24 });
25
26 setLoading(true);
27 setShowOtp(true);
28 } catch (e) {
29 Alert.alert("Error sending OTP Code. Check logs for more details.");
30
31 console.log("Error seding OTP CODE: ", e);
32 }
33 },
34 [authenticate]
35 );
36
37 const completeAuth = useCallback(() => {
38 setLoading(false);
39 setShowOtp(false);
40 }, []);
41
42 return (
43 <View>
44 {user && (
45 <>
46 <Text>User Authenticated As: {user.email}</Text>
47 <Text>{user.address}</Text>
48 </>
49 )}
50
51 <Text style={{ fontSize: 16 }}>Enter Email</Text>
52 <TextInput
53 value={email}
54 style={{ fontSize: 20 }}
55 onChangeText={setEmail}
56 placeholder="Enter Email"
57 autoCapitalize="none"
58 />
59 <Button
60 title={loading ? "Loading" : "Sign In"}
61 disabled={loading}
62 onPress={() => performAuthRequest(email)}
63 />
64
65 <OtpPopUp
66 show={showOtp}
67 completeAuth={completeAuth}
68 close={() => {
69 setShowOtp(false);
70 setLoading(false);
71 }}
72 />
73 </View>
74 );
75};