Appearance
Email
To authenticate your users with a one-time passcode (OTP) sent to their email address, use the useLoginWithEmail
hook.
The useLoginWithEmail
hook returns two methods necessary for the authentication flow:
sendCode
: sends an OTP to the user's email addressloginWithCode
: authenticates the user with the OTP sent to their email address
The hook also returns a state
variable that tracks the flow state of the login process.
Sending the OTP
To authenticate your users with email, first, prompt your user for their email address and send an OTP to this address using the sendCode
method. As a required parameter to sendCode
, pass a JSON object with a variable containing the user's provided email addressas a string. When invoked, this method will return a Promise that:
- resolves to
void
if the OTP was successfully sent - rejects if there was an error
Authenticating with the OTP
Once the OTP has been sent via sendCode
, prompt your user for the OTP sent to their email address and use the loginWithCode
method to authenticate them. As a required parameter to loginWithCode
, pass a JSON object with a variable code
containing the OTP provided by the user as a string. When invoked, this method will return a Promise that:
- resolves to
void
if the entered OTP was correct, and the user has successfully authenticated - rejects if there was an error, such as an invalid code entry
To handle cases where a user accidentally enters the wrong OTP in your prompt, for a given OTP delivered to the user's email with sendCode
, you may call loginWithCode
up to a maximum of 5 times, to allow the user to retry if the code they entered is invalid. After 5 attempts, the OTP is no longer valid, and you must request a new code for the user via sendCode
.
Example usage
As an example, you might set up a LoginWithEmail
component for your app that uses these methods, like below:
tsx
import {useState} from 'react';
import {useLoginWithEmail} from '@privy-io/react-auth';
export default function LoginWithEmail() {
// Local State
const [email, setEmail] = useState('');
const [code, setCode] = useState('');
// Privy
const {state, sendCode, loginWithCode} = useLoginWithEmail();
return (
<div>
{/* Prompt your user to enter their email address */}
<input onChange={(e) => setEmail(e.currentTarget.value)} />
{/* Once an email has been entered, send the OTP to it on click */}
<button onClick={() => sendCode({email})}>Send Code</button>
{/* Prompt your user to enter the OTP */}
<input onChange={(e) => setCode(e.currentTarget.value)} />
{/* Once an OTP has been entered, submit it to Privy on click */}
<button onClick={() => loginWithCode({code})}>Log in</button>
</div>
);
}
Tracking login flow state
The state
variable returned from all of the useLoginWithEmail
hook will always be one of the following values.
ts
type OtpFlowState =
| {status: 'initial'}
| {status: 'error'; error: Error | null}
| {status: 'sending-code'}
| {status: 'awaiting-code-input'}
| {status: 'submitting-code'}
| {status: 'done'};
Learn more about conditional rendering with the state
variable in the state guide.