Email OTP
The Email OTP plugin allows user to sign in, verify their email, or reset their password using a one-time password (OTP) sent to their email address.
Installation
Add the plugin to your auth config
Add the emailOTP
plugin to your auth config and implement the sendVerificationOTP()
method.
import { betterAuth } from "better-auth"
import { emailOTP } from "better-auth/plugins"
export const auth = betterAuth({
// ... other config options
plugins: [
emailOTP({
async sendVerificationOTP({ email, otp, type }) {
if (type === "sign-in") {
// Send the OTP for sign in
} else if (type === "email-verification") {
// Send the OTP for email verification
} else {
// Send the OTP for password reset
}
},
})
]
})
Add the client plugin
import { createAuthClient } from "better-auth/client"
import { emailOTPClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
emailOTPClient()
]
})
Usage
Send an OTP
Use the sendVerificationOtp()
method to send an OTP to the user's email address.
const { data, error } = await authClient.emailOtp.sendVerificationOtp({ email: "[email protected]", // required type: "sign-in", // required});
Prop | Description | Type |
---|---|---|
email | Email address to send the OTP. | string |
type | Type of the OTP. sign-in , email-verification , or forget-password . | "email-verification" | "sign-in" | "forget-password" |
Check an OTP (optional)
Use the checkVerificationOtp()
method to check if an OTP is valid.
const { data, error } = await authClient.emailOtp.checkVerificationOtp({ email: "[email protected]", // required type: "sign-in", // required otp: "123456", // required});
Prop | Description | Type |
---|---|---|
email | Email address to send the OTP. | string |
type | Type of the OTP. sign-in , email-verification , or forget-password . | "email-verification" | "sign-in" | "forget-password" |
otp | OTP sent to the email. | string |
Sign In with OTP
To sign in with OTP, use the sendVerificationOtp()
method to send a "sign-in" OTP to the user's email address.
const { data, error } = await authClient.emailOtp.sendVerificationOtp({ email: "[email protected]", // required type: "sign-in", // required});
Prop | Description | Type |
---|---|---|
email | Email address to send the OTP. | string |
type | Type of the OTP. | "sign-in" |
Once the user provides the OTP, you can sign in the user using the signIn.emailOtp()
method.
const { data, error } = await authClient.signIn.emailOtp({ email: "[email protected]", // required otp: "123456", // required});
Prop | Description | Type |
---|---|---|
email | Email address to sign in. | string |
otp | OTP sent to the email. | string |
If the user is not registered, they'll be automatically registered. If you want to prevent this, you can pass disableSignUp
as true
in the options.
Verify Email with OTP
To verify the user's email address with OTP, use the sendVerificationOtp()
method to send an "email-verification" OTP to the user's email address.
const { data, error } = await authClient.emailOtp.sendVerificationOtp({ email: "[email protected]", // required type: "email-verification", // required});
Prop | Description | Type |
---|---|---|
email | Email address to send the OTP. | string |
type | Type of the OTP. | "email-verification" |
Once the user provides the OTP, use the verifyEmail()
method to complete email verification.
const { data, error } = await authClient.emailOtp.verifyEmail({ email: "[email protected]", // required otp: "123456", // required});
Prop | Description | Type |
---|---|---|
email | Email address to verify. | string |
otp | OTP to verify. | string |
Reset Password with OTP
To reset the user's password with OTP, use the forgetPassword.emailOTP()
method to send a "forget-password" OTP to the user's email address.
const { data, error } = await authClient.forgetPassword.emailOtp({ email: "[email protected]", // required});
Prop | Description | Type |
---|---|---|
email | Email address to send the OTP. | string |
Once the user provides the OTP, use the checkVerificationOtp()
method to check if it's valid (optional).
const { data, error } = await authClient.emailOtp.checkVerificationOtp({ email: "[email protected]", // required type: "forget-password", // required otp: "123456", // required});
Prop | Description | Type |
---|---|---|
email | Email address to send the OTP. | string |
type | Type of the OTP. | "forget-password" |
otp | OTP sent to the email. | string |
Then, use the resetPassword()
method to reset the user's password.
const { data, error } = await authClient.emailOtp.resetPassword({ email: "[email protected]", // required otp: "123456", // required password: "new-secure-password", // required});
Prop | Description | Type |
---|---|---|
email | Email address to reset the password. | string |
otp | OTP sent to the email. | string |
password | New password. | string |
Override Default Email Verification
To override the default email verification, pass overrideDefaultEmailVerification: true
in the options. This will make the system use an email OTP instead of the default verification link whenever email verification is triggered. In other words, the user will verify their email using an OTP rather than clicking a link.
import { betterAuth } from "better-auth";
export const auth = betterAuth({
plugins: [
emailOTP({
overrideDefaultEmailVerification: true,
async sendVerificationOTP({ email, otp, type }) {
// Implement the sendVerificationOTP method to send the OTP to the user's email address
},
}),
],
});
Options
-
sendVerificationOTP
: A function that sends the OTP to the user's email address. The function receives an object with the following properties:email
: The user's email address.otp
: The OTP to send.type
: The type of OTP to send. Can be "sign-in", "email-verification", or "forget-password".
-
otpLength
: The length of the OTP. Defaults to6
. -
expiresIn
: The expiry time of the OTP in seconds. Defaults to300
seconds.
import { betterAuth } from "better-auth"
export const auth = betterAuth({
plugins: [
emailOTP({
otpLength: 8,
expiresIn: 600
})
]
})
-
sendVerificationOnSignUp
: A boolean value that determines whether to send the OTP when a user signs up. Defaults tofalse
. -
disableSignUp
: A boolean value that determines whether to prevent automatic sign-up when the user is not registered. Defaults tofalse
. -
generateOTP
: A function that generates the OTP. Defaults to a random 6-digit number. -
allowedAttempts
: The maximum number of attempts allowed for verifying an OTP. Defaults to3
. After exceeding this limit, the OTP becomes invalid and the user needs to request a new one.
import { betterAuth } from "better-auth"
export const auth = betterAuth({
plugins: [
emailOTP({
allowedAttempts: 5, // Allow 5 attempts before invalidating the OTP
expiresIn: 300
})
]
})
When the maximum attempts are exceeded, the verifyOTP
, signIn.emailOtp
, verifyEmail
, and resetPassword
methods will return an error with code MAX_ATTEMPTS_EXCEEDED
.
storeOTP
: The method to store the OTP in your database, wetherencrypted
,hashed
orplain
text. Default isplain
text.
Note: This will not affect the OTP sent to the user, it will only affect the OTP stored in your database.
Alternatively, you can pass a custom encryptor or hasher to store the OTP in your database.
Custom encryptor
emailOTP({
storeOTP: {
encrypt: async (otp) => {
return myCustomEncryptor(otp);
},
decrypt: async (otp) => {
return myCustomDecryptor(otp);
},
}
})
Custom hasher
emailOTP({
storeOTP: {
hash: async (otp) => {
return myCustomHasher(otp);
},
}
})