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.

Email and password sign in form showing email field, password field, forgot password link, and sign in button

Configuration

apps/web/.env.local

# Enable email/password sign in (default: true)
NEXT_PUBLIC_AUTH_PASSWORD=true

Component

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

  1. User enters email and password
  2. Better Auth validates credentials against the database
  3. If MFA is enabled for the user, they're redirected to /auth/verify
  4. On success, a session cookie is set and user is redirected to the dashboard

Passwordless authentication via email link. Disabled by default.

Magic link sign in form showing email field and send magic link button

Configuration

apps/web/.env.local

# Enable magic link sign in (default: false)
NEXT_PUBLIC_AUTH_MAGIC_LINK=true

How It Works

  1. User enters their email address
  2. Server sends an email with a secure, time-limited link
  3. User clicks the link to authenticate
  4. Session is created automatically

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.

Social provider sign in buttons showing Continue with Google option

Google Configuration

apps/web/.env.local

GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret

To get these credentials:

  1. Go to Google Cloud Console
  2. Create or select a project
  3. Navigate to APIs & Services > Credentials
  4. Create an OAuth 2.0 Client ID
  5. Add http://localhost:3000/api/auth/callback/google to authorized redirect URIs
  6. 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.

MFA verification form showing 6-digit code input field

How It Works

  1. User signs in with email/password
  2. Better Auth detects MFA is enabled for this user
  3. User is redirected to /auth/verify
  4. User enters the 6-digit code from their authenticator app
  5. 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

  1. Verify the user exists in the database
  2. Check that the password is correct
  3. Ensure email verification is complete (if required)

Social Sign In Redirect Fails

  1. Verify callback URLs match in provider settings
  2. Check that client ID and secret are correct
  3. Ensure NEXT_PUBLIC_SITE_URL matches your domain
  1. Check spam/junk folder
  2. Verify mailer configuration
  3. In development, check the console for the logged link

Previous: Authentication Overview ← | Next: Sign Up →