Authentication Methods
Configure email/password, magic link, passkey, and OAuth authentication methods in your SaaS application.
Choose how users sign in - email/password, passwordless magic links, passkeys, or OAuth - by setting environment variables. No code changes required.
This page is part of the Authentication documentation.
The kit supports email/password (enabled by default), magic links (disabled by default), passkeys (disabled by default), and OAuth social providers. Toggle each method with environment variables. OAuth buttons only appear for providers listed in NEXT_PUBLIC_AUTH_OAUTH_PROVIDERS and configured server-side. Password requirements (length, special characters, numbers, uppercase) are also configurable via environment variables, and the sign-in forms adapt automatically.
Authentication methods are the ways users prove their identity - credentials (email/password), passwordless (magic link), device-bound (passkey/WebAuthn), or delegated (OAuth via Google, GitHub, etc.).
- Enable multiple methods when: you want to offer users flexibility. Many SaaS apps offer both OAuth and email/password.
If unsure: start with email/password and Google OAuth. Add magic links later if users request it.
Supported Methods
| Method | Default | Environment Variable |
|---|---|---|
| Email/Password | Enabled | NEXT_PUBLIC_AUTH_PASSWORD=true |
| Magic Link | Disabled | NEXT_PUBLIC_AUTH_MAGIC_LINK=true |
| Passkey | Disabled | ENABLE_PASSKEY + NEXT_PUBLIC_AUTH_PASSKEY=true (see below) |
| OAuth | Disabled until configured | See Social Providers |
Email and Password Authentication
Enable or disable with:
./.env.local
NEXT_PUBLIC_AUTH_PASSWORD=truePassword Requirements
Configure password complexity rules:
./.env.local
NEXT_PUBLIC_PASSWORD_MIN_LENGTH=8NEXT_PUBLIC_PASSWORD_MAX_LENGTH=99NEXT_PUBLIC_PASSWORD_REQUIRE_SPECIAL_CHARS=trueNEXT_PUBLIC_PASSWORD_REQUIRE_NUMBERS=trueNEXT_PUBLIC_PASSWORD_REQUIRE_UPPERCASE=trueThese settings enforce rules on both registration and password change forms. The UI displays requirements to users in real-time.
Email Verification
Email verification is required by default. Users must click a verification link before accessing the app. This prevents account takeover via email typos and confirms the user controls the email address.
Magic Link Authentication
Passwordless sign-in via email links:
./.env.local
NEXT_PUBLIC_AUTH_MAGIC_LINK=trueWhen enabled, users enter their email and receive a sign-in link. Clicking the link authenticates them without a password. Links expire after 10 minutes.
Requires email configuration: Magic links only work if your mailer is properly configured. See Email Configuration.
Passkey Authentication
Passwordless, phishing-resistant sign-in using WebAuthn (biometrics or a hardware security key). Unlike the other methods, passkeys have two gates because their database table must be generated ahead of time and can't depend on a runtime variable.
1. Build-time flag — set ENABLE_PASSKEY in packages/better-auth/src/auth.features.ts:
packages/better-auth/src/auth.features.ts
export const ENABLE_PASSKEY = true;This constant is read by both the runtime auth config (auth.ts) and the schema-generation entrypoint (config.ts). While false, the plugin is not registered server-side - the /passkey/* endpoints don't exist and the passkey table is not generated (not merely hidden in the UI).
2. Generate the table and migrate:
pnpm --filter @kit/better-auth schema:generatepnpm --filter @kit/database prisma migrate dev --name add-passkey3. Runtime UI flag — show the sign-in button and settings card:
./.env.local
NEXT_PUBLIC_AUTH_PASSKEY=trueWhen enabled, a "Sign in with a passkey" button appears on the sign-in page and a Passkeys card appears under Settings → Security where signed-in users register and remove passkeys. Passkeys are bound to an existing account, so users register one after they already have an account - there is no passkey button on the sign-up form.
The relying party domain is derived from NEXT_PUBLIC_SITE_URL (localhost in development, your real domain in production); a mismatch causes the browser to reject the passkey.
Common Pitfalls
- Enabling magic links without email configuration: Links won't be delivered. Configure your mailer first.
- Setting password requirements too strict: Users abandon registration. 8+ characters with one number is a reasonable minimum.
- Disabling all auth methods: At least one method must be enabled or users can't sign in.
- Forgetting email verification in production: Without verification, typos in email addresses create orphaned accounts.
- Mixing environment variable formats: Use
trueorfalse(lowercase strings), not1oryes.
Frequently Asked Questions
Can I require MFA for all users?
How do I disable email/password and only allow OAuth?
Can users have both password and OAuth linked?
Where are the sign-in forms?
How do I customize the password reset flow?
Next: Social Providers →