Email OTP Authentication

Email OTP authentication allows you to log in and sign up users using an email address. Your users will receive six-digit code in their inbox which they can enter in your site to complete login.

For setting up an account config, see the Signer Quickstart.

Authenticate a user

import { 
import signer
signer
} from "./signer";
// send the email // Promise resolves when the user is fully authenticated (OTP + optional MFA), // even if final step completes in another tab/window await
import signer
signer
.
any
authenticate
({
type: string
type
: "email",
emailMode: string
emailMode
: "otp",
email: string
email
: "[email protected]",
}); // later once the user has entered the code from their email // Promise resolves when the user is fully authenticated (OTP + optional MFA), // even if final step completes in another tab/window await
import signer
signer
.
any
authenticate
({
type: string
type
: "otp",
otpCode: string
otpCode
: "123456",
});
import { 
class AlchemyWebSigner

A SmartAccountSigner that can be used with any SmartContractAccount

AlchemyWebSigner
} from "@account-kit/signer";
export const
const signer: AlchemyWebSigner
signer
= new
new AlchemyWebSigner(params: AlchemySignerParams): AlchemyWebSigner

Initializes an instance with the provided Alchemy signer parameters after parsing them with a schema.

AlchemyWebSigner
({
client: ({ connection: { apiKey: string; rpcUrl?: undefined; jwt?: undefined; } | { jwt: string; rpcUrl?: undefined; apiKey?: undefined; } | { rpcUrl: string; apiKey?: undefined; jwt?: undefined; } | { rpcUrl: string; jwt: string; apiKey?: undefined; }; ... 4 more ...; enablePopupOauth?: boolean | undefined; } | AlchemySignerWebClient) & (AlchemySignerWebClient | ... 1 more ... | undefined)
client
: {
connection: { apiKey: string; }
connection
: {
apiKey: string
apiKey
: "API_KEY",
},
iframeConfig: { iframeContainerId: string; }
iframeConfig
: {
iframeContainerId: string
iframeContainerId
: "alchemy-signer-iframe-container",
}, }, });

Track Authentication Status

Use signer.on("statusChanged", callback) and the AlchemySignerStatus enum to respond to OTP/MFA prompts and completion:

import { 
import signer
signer
} from "./signer";
import {
enum AlchemySignerStatus
AlchemySignerStatus
} from "@account-kit/signer";
import signer
signer
.
any
on
("statusChanged", (
status: any
status
) => {
switch (
status: any
status
) {
case
enum AlchemySignerStatus
AlchemySignerStatus
.
function (enum member) AlchemySignerStatus.AWAITING_EMAIL_AUTH = "AWAITING_EMAIL_AUTH"
AWAITING_EMAIL_AUTH
:
// show OTP input UI break; case
enum AlchemySignerStatus
AlchemySignerStatus
.
function (enum member) AlchemySignerStatus.AWAITING_MFA_AUTH = "AWAITING_MFA_AUTH"
AWAITING_MFA_AUTH
:
// show TOTP input UI break; case
enum AlchemySignerStatus
AlchemySignerStatus
.
function (enum member) AlchemySignerStatus.CONNECTED = "CONNECTED"
CONNECTED
:
// authentication complete break; } });
import { 
class AlchemyWebSigner

A SmartAccountSigner that can be used with any SmartContractAccount

AlchemyWebSigner
} from "@account-kit/signer";
export const
const signer: AlchemyWebSigner
signer
= new
new AlchemyWebSigner(params: AlchemySignerParams): AlchemyWebSigner

Initializes an instance with the provided Alchemy signer parameters after parsing them with a schema.

AlchemyWebSigner
({
client: ({ connection: { apiKey: string; rpcUrl?: undefined; jwt?: undefined; } | { jwt: string; rpcUrl?: undefined; apiKey?: undefined; } | { rpcUrl: string; apiKey?: undefined; jwt?: undefined; } | { rpcUrl: string; jwt: string; apiKey?: undefined; }; ... 4 more ...; enablePopupOauth?: boolean | undefined; } | AlchemySignerWebClient) & (AlchemySignerWebClient | ... 1 more ... | undefined)
client
: {
connection: { apiKey: string; }
connection
: {
apiKey: string
apiKey
: "API_KEY",
},
iframeConfig: { iframeContainerId: string; }
iframeConfig
: {
iframeContainerId: string
iframeContainerId
: "alchemy-signer-iframe-container",
}, }, });