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

MethodDefaultEnvironment Variable
Email/PasswordEnabledNEXT_PUBLIC_AUTH_PASSWORD=true
Magic LinkDisabledNEXT_PUBLIC_AUTH_MAGIC_LINK=true
PasskeyDisabledENABLE_PASSKEY + NEXT_PUBLIC_AUTH_PASSKEY=true (see below)
OAuthDisabled until configuredSee Social Providers

Email and Password Authentication

Enable or disable with:

./.env.local

NEXT_PUBLIC_AUTH_PASSWORD=true

Password Requirements

Configure password complexity rules:

./.env.local

NEXT_PUBLIC_PASSWORD_MIN_LENGTH=8
NEXT_PUBLIC_PASSWORD_MAX_LENGTH=99
NEXT_PUBLIC_PASSWORD_REQUIRE_SPECIAL_CHARS=true
NEXT_PUBLIC_PASSWORD_REQUIRE_NUMBERS=true
NEXT_PUBLIC_PASSWORD_REQUIRE_UPPERCASE=true

These 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.

Passwordless sign-in via email links:

./.env.local

NEXT_PUBLIC_AUTH_MAGIC_LINK=true

When 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:generate
pnpm --filter @kit/database prisma migrate dev --name add-passkey

3. Runtime UI flag — show the sign-in button and settings card:

./.env.local

NEXT_PUBLIC_AUTH_PASSKEY=true

When 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 true or false (lowercase strings), not 1 or yes.

Frequently Asked Questions

Can I require MFA for all users?
MFA is opt-in per user by default. To require it for all users, you would need to customize the sign-in flow to check MFA status and redirect to setup. See the MFA Configuration documentation.
How do I disable email/password and only allow OAuth?
Set NEXT_PUBLIC_AUTH_PASSWORD=false and ensure at least one OAuth provider is configured. The sign-in form adapts to show only OAuth buttons.
Can users have both password and OAuth linked?
Yes. Better Auth supports account linking. A user who signed up with Google can later add a password, and vice versa.
Where are the sign-in forms?
Forms are in packages/auth/src/components/. They read environment variables to show/hide auth method options.
How do I customize the password reset flow?
The flow uses Better Auth built-in password reset with email verification. Customize the email template in packages/email-templates/src/emails/password-reset.email.tsx.

Next: Social Providers →