Authentication Methods
Configure email/password, magic link, and OAuth authentication methods in your SaaS application.
Enable the authentication methods your users expect. The kit supports email/password, magic links (passwordless), and OAuth providers - toggle each with environment variables. This guidance applies to the Drizzle kit.
This page is part of the Authentication documentation.
Available Methods
| Method | Default | Use Case |
|---|---|---|
| Email/Password | Enabled | Traditional sign-in with credentials |
| Magic Link | Disabled | Passwordless sign-in via email link |
| OAuth | Disabled | Social login (Google, GitHub, etc.) |
Most SaaS apps start with email/password. Add magic links for users who forget passwords frequently. Add OAuth to reduce sign-up friction.
Email and Password Authentication
Email/password is the most common auth method. Users register with their email and a password, then sign in with those credentials.
Enable/Disable
apps/web/.env.local
NEXT_PUBLIC_AUTH_PASSWORD=trueSet to false to disable email/password authentication entirely (useful if you only want OAuth).
Password Requirements
Configure password complexity rules:
apps/web/.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=true| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_PASSWORD_MIN_LENGTH | 8 | Minimum password length |
NEXT_PUBLIC_PASSWORD_MAX_LENGTH | 99 | Maximum password length |
NEXT_PUBLIC_PASSWORD_REQUIRE_SPECIAL_CHARS | true | Require special characters |
NEXT_PUBLIC_PASSWORD_REQUIRE_NUMBERS | true | Require at least one number |
NEXT_PUBLIC_PASSWORD_REQUIRE_UPPERCASE | true | Require uppercase letter |
Email Verification
Email verification is required by default. Users receive a verification email after registration and must click the link before accessing the app.
The verification flow:
- User registers with email/password
- Better Auth sends verification email
- User clicks verification link
- User is automatically signed in
Email verification protects against:
- Fake accounts with invalid emails
- Account takeover via typo-squatting
- Spam registrations
Password Reset
Users can reset forgotten passwords:
- User clicks "Forgot password" on sign-in form
- User enters their email address
- Better Auth sends reset email with secure link
- User clicks link and sets new password
- User is signed in with new password
Reset links expire after a configurable time (default: 1 hour).
Magic Link Authentication
Magic links provide passwordless authentication. Users enter their email, receive a link, and click to sign in - no password needed.
Enable Magic Links
apps/web/.env.local
NEXT_PUBLIC_AUTH_MAGIC_LINK=trueHow It Works
- User enters email on sign-in form
- User clicks "Sign in with Magic Link"
- Better Auth sends email with secure link
- User clicks link in email
- User is signed in automatically
Implementation
The magic link plugin is configured in packages/better-auth/src/plugins/magic-link.ts:
import { magicLink } from 'better-auth/plugins/magic-link';export const magicLinkPlugin = magicLink({ sendMagicLink: async ({ email, url }) => { const { sendMagicLinkEmail } = await import('../emails/send-magic-link-email'); // Log in development mode if (process.env.NODE_ENV === 'development') { console.log(`[DEV] Magic link for ${email}: ${url}`); } await sendMagicLinkEmail({ email, url, productName: getProductName(), }); },});In development, magic links are logged to the console for easy testing without checking email.
When to Use Magic Links
Good for:
- Users who frequently forget passwords
- Low-friction onboarding
- Apps where security > convenience (each sign-in requires email access)
Consider alternatives when:
- Users sign in frequently (magic links add friction)
- Email delivery is unreliable
- Users need offline access
Client Usage
Sign In with Password
import { authClient } from '@kit/better-auth/client';const result = await authClient.signIn.email({ email: 'user@example.com', password: 'securepassword123',});if (result.error) { console.error('Sign in failed:', result.error.message);}Sign In with Magic Link
import { authClient } from '@kit/better-auth/client';// Request magic linkawait authClient.signIn.magicLink({ email: 'user@example.com', callbackURL: '/dashboard',});// User receives email and clicks link to complete sign-inSign Up
import { authClient } from '@kit/better-auth/client';const result = await authClient.signUp.email({ email: 'user@example.com', password: 'securepassword123', name: 'John Doe',});if (result.error) { console.error('Sign up failed:', result.error.message);}Password Reset
import { authClient } from '@kit/better-auth/client';// Request password resetawait authClient.forgetPassword({ email: 'user@example.com', redirectTo: '/auth/password-reset',});// After user clicks email link and enters new passwordawait authClient.resetPassword({ newPassword: 'newSecurePassword123',});Common Pitfalls
- Disabling all auth methods: At least one method must be enabled.
- Weak password requirements in production: Use strong defaults. Weak passwords are a security risk.
- Not testing email delivery: Magic links and verification emails require working email configuration.
- Missing
NEXT_PUBLIC_prefix: Auth method toggles need the public prefix to work on the client.
Frequently Asked Questions
Can I enable both password and magic link authentication?
How do I customize password requirements?
What happens if email verification fails?
Can I disable email verification?
How long do magic links last?
Next: Social Providers →