Phone login with SMS codes
auth.requestSmsOtp sends a short-lived code through the configured SMS provider. For phone login, auth.verifySmsOtp consumes it and returns a session or an MFA challenge.
Configure the SMS provider
Pass the send function from the application's SMS service when the backend creates its Own Auth instance.
import { createOwnAuth, type SmsProvider } from "own-auth";
type SendText = (input: {
to: string;
body: string;
}) => Promise<void>;
export function createAuth(sendText: SendText) {
const smsProvider: SmsProvider = {
async send({ to, code }) {
await sendText({
to,
body: `Your sign-in code is ${code}`,
});
},
};
return createOwnAuth({
tokenPepper: process.env.OWN_AUTH_TOKEN_PEPPER,
smsProvider,
});
}Request the code
await auth.requestSmsOtp({ phone });
return {
message: "If that number can sign in, a code is on its way.",
};Verify the code
export async function verifyPhoneLogin(phone: string, code: string) {
const result = await auth.verifySmsOtp({
phone,
code,
});
if (result.status === "mfa_required") {
return {
status: result.status,
challengeToken: result.challengeToken,
methods: result.methods,
expiresAt: result.expiresAt,
};
}
if (result.status === "verified") {
throw new Error("Unexpected non-login SMS result");
}
return {
status: result.status,
userId: result.user.id,
sessionToken: result.sessionToken,
expiresAt: result.session.expiresAt,
};
}Own Auth normalizes the phone number, stores a protected code hash, limits requests and verification attempts, and consumes the code after successful verification. A complete result contains the new aal1 session; an account with another factor returns mfa_required.