Sign In
Sign in with email/password, magic link, or social providers. Configure MFA and customize the authentication flow.
Sign In Methods
Available authentication methods in the kit.
The sign in page supports multiple authentication methods that can be enabled or disabled independently. Users see only the methods you've configured. This guide applies to the Drizzle kit.
Page location: apps/web/app/[locale]/auth/sign-in/page.tsx Route: /auth/sign-in
Email/Password Sign In
The default authentication method. Users enter their email and password to sign in.

Configuration
apps/web/.env.local
# Enable email/password sign in (default: true)NEXT_PUBLIC_AUTH_PASSWORD=trueComponent
The sign in form is rendered by SignInMethodsContainer:
packages/auth/src/components/sign-in-methods-container.tsx
<SignInMethodsContainer paths={{ returnPath: '/dashboard', }} providers={{ password: true, magicLink: false, oAuth: ['google'], }}/>Flow
- User enters email and password
- Better Auth validates credentials against the database
- If MFA is enabled for the user, they're redirected to
/auth/verify - On success, a session cookie is set and user is redirected to the dashboard
Magic Link Sign In
Passwordless authentication via email link. Disabled by default.

Configuration
apps/web/.env.local
# Enable magic link sign in (default: false)NEXT_PUBLIC_AUTH_MAGIC_LINK=trueHow It Works
- User enters their email address
- Server sends an email with a secure, time-limited link
- User clicks the link to authenticate
- Session is created automatically
MFA bypass
Magic link authentication bypasses MFA. If you require MFA for all users, consider disabling magic links. This is by design since the email itself serves as a second factor (possession of the email account).
Email Configuration
Magic link emails are sent using your configured mailer. In development, the link is also logged to the console:
[DEV] Magic link for user@example.com: http://localhost:3000/api/auth/magic-link/verify?token=...For production, configure your email provider.
Social Provider Sign In
OAuth authentication with Google, GitHub, or other providers.

Google Configuration
apps/web/.env.local
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.comGOOGLE_CLIENT_SECRET=your-client-secretTo get these credentials:
- Go to Google Cloud Console
- Create or select a project
- Navigate to APIs & Services > Credentials
- Create an OAuth 2.0 Client ID
- Add
http://localhost:3000/api/auth/callback/googleto authorized redirect URIs - For production, add your production callback URL
Adding More Providers
Edit packages/better-auth/src/plugins/social-providers.ts to add providers:
packages/better-auth/src/plugins/social-providers.ts
export function createSocialProviderPlugin(): SocialProviders { const googleSocialProviderPlugin = createGoogleProviderPlugin(); return { ...googleSocialProviderPlugin, // Add GitHub (requires GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET env vars) github: { clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, }, };}See the Better Auth Social Providers documentation for the full list of supported providers.
MFA Challenge
When a user with MFA enabled signs in with email/password, they're redirected to a verification page.

How It Works
- User signs in with email/password
- Better Auth detects MFA is enabled for this user
- User is redirected to
/auth/verify - User enters the 6-digit code from their authenticator app
- On success, session is created and user is redirected
Enabling MFA
Users enable MFA from their security settings at /settings/security. See the MFA documentation for details.
Client-Side Handling
The auth client automatically handles MFA redirects:
packages/better-auth/src/auth-client.ts
twoFactorClient({ onTwoFactorRedirect() { const redirect = new URLSearchParams(location.search).get('redirect'); window.location.href = '/auth/verify' + (redirect ? `?redirect=${redirect}` : ''); },}),Programmatic Sign In
For custom sign in flows, use the auth client directly:
'use client';import { authClient } from '@kit/better-auth/client';async function handleSignIn(email: string, password: string) { const result = await authClient.signIn.email({ email, password, }); if (result.error) { console.error(result.error.message); return; } // User is signed in, redirect or update UI window.location.href = '/dashboard';}Customizing the Sign In Page
Change the Layout
Edit the auth layout at apps/web/app/[locale]/auth/layout.tsx:
apps/web/app/[locale]/auth/layout.tsx
export default function AuthLayout({ children }) { return ( <AuthLayoutWrapper> <YourCustomBranding /> {children} </AuthLayoutWrapper> );}Add Terms of Service
The sign in form can display a terms of service checkbox. Configure it in the SignInMethodsContainer props.
Common Issues
"Invalid credentials" Error
- Verify the user exists in the database
- Check that the password is correct
- Ensure email verification is complete (if required)
Social Sign In Redirect Fails
- Verify callback URLs match in provider settings
- Check that client ID and secret are correct
- Ensure
NEXT_PUBLIC_SITE_URLmatches your domain
Magic Link Not Received
- Check spam/junk folder
- Verify mailer configuration
- In development, check the console for the logged link
Previous: Authentication Overview ← | Next: Sign Up →