User accounts & auth
env.AUTH is a complete authentication system for your app's own end-users — email + password, sessions, email verification, password reset, and email-based two-factor. It manages its own tables and session cookie; you call methods and return the responses it hands back.
Sign up & sign in
signUp and signIn return a result object. On success it includes a response — a Response with the session cookie already set. Return it (or copy its Set-Cookie) so the browser is signed in:
// api/login.js
export default {
async fetch(request, env, ctx) {
const { email, password } = await request.json();
const r = await env.AUTH.signIn({ email, password });
if (!r.ok) return Response.json({ error: r.error }, { status: 401 });
if (r.requires2fa) {
// a code was emailed; collect it, then call verifyTwoFactorOtp
await env.AUTH.sendTwoFactorOtp({ otpToken: r.otpToken });
return Response.json({ requires2fa: true, otpToken: r.otpToken });
}
return r.response; // session cookie set
},
};signUp({ email, password, name? }) works the same way and returns { ok, user, response }.
Reading the current user
On any request, read who's signed in. getUser returns the user or null; requireUser throws a 401 response if there's no session:
const user = await env.AUTH.getUser(request);
// => { id, email, name, emailVerified, twoFactorEnabled, createdAt } | nullScope your data queries to user.id.
Two-factor (email OTP)
When a user has 2FA enabled, signIn returns requires2fa: true and an otpToken instead of a session. Email the code, then verify it to complete sign-in:
sendTwoFactorOtp({ otpToken })— email the code.verifyTwoFactorOtp({ otpToken, code })— returns{ ok, user, response }; return theresponseto set the session.enableTwoFactor(request)/disableTwoFactor(request, { password }).
Other methods
signOut(request)→ aResponsethat clears the session cookie.updateUser(request, { name })— update profile fields.changePassword(request, { current, new })— revokes other sessions on success.sendVerificationEmail(request)·verifyEmail(token).requestPasswordReset(email)(always returns{ ok: true }to avoid account enumeration) ·resetPassword({ token, newPassword }).
Sessions & storage
Sessions use an HttpOnly; Secure; SameSite=Lax cookie with a 30-day lifetime. User and session data live in the reserved _cr_users, _cr_sessions, and _cr_email_tokens tables in your app's database — don't touch these directly (see Database).