# Authentication Features

> Implement and customize authentication flows including sign in, sign up, password reset, and MFA with Better Auth in your Next.js SaaS application.

*Canonical: https://makerkit.dev/docs/nextjs-prisma/authentication/overview*

---

Use the pre-built authentication flows to handle sign in, sign up, password reset, and MFA. The kit handles email/password, magic links, passkeys, OAuth providers, and TOTP-based multi-factor authentication out of the box.

The Next.js Prisma SaaS Kit provides complete authentication UI and logic built on [Better Auth](https://www.better-auth.com/). Sign-in and sign-up forms handle email/password, magic links, and OAuth providers configured in `NEXT_PUBLIC_AUTH_OAUTH_PROVIDERS`, plus passkeys on the sign-in form. Password reset sends secure email links automatically. MFA uses TOTP with authenticator apps like Google Authenticator or Authy. Session handling provides `getSession()` for React Server Components and `authClient.useSession()` for client components. All flows are pre-built and work immediately after configuration.

Authentication features are the user-facing flows (sign in, sign up, password reset, MFA) and the server-side utilities (`getSession`, `requireAdmin`) that verify user identity and protect routes in your Next.js App Router application.

**Use this documentation when:** you're customizing sign-in behavior, adding MFA, protecting routes, or debugging session issues.

**Use Better Auth documentation when:** you need to configure the auth backend (plugins, session duration, database adapter). See [Better Auth Configuration](../better-auth/overview).

**If unsure:** start here for UI and route protection; go to Better Auth docs for backend configuration.

## Features

- Email/Password Sign In and Sign Up
- Magic Link (Passwordless) Authentication
- OAuth Social Providers (Google, GitHub, Apple, etc.)
- Password Reset via Email
- Multi-Factor Authentication (MFA/TOTP)
- Email Verification
- Session Management and Route Protection
- CAPTCHA Protection (Cloudflare Turnstile)
- Rate Limiting on Auth Endpoints

## Documentation Structure

| Page | Purpose |
|------|---------|
| [Sign In](./sign-in) | Email/password, magic link, passkey, OAuth, MFA challenge flows |
| [Sign Up](./sign-up) | Account creation and email verification |
| [Password Reset](./password-reset) | Forgot password and recovery flow |
| [Session Handling](./session-handling) | Route protection and session access |

## Related Documentation

| Page | Purpose |
|------|---------|
| [Better Auth Setup](../better-auth/setup) | Core auth configuration and secrets |
| [Auth Methods](../better-auth/auth-methods) | Enable/disable email, magic link, passkey, OAuth |
| [Social Providers](../better-auth/social-providers) | Configure Google, GitHub, Apple OAuth |
| [MFA Configuration](../better-auth/mfa-configuration) | TOTP multi-factor authentication |
| [Captcha Plugin](../better-auth/captcha-plugin) | Bot protection with Cloudflare Turnstile |

## Auth Routes

| Route | Purpose |
|-------|---------|
| `/auth/sign-in` | Sign in page |
| `/auth/sign-up` | Sign up page |
| `/auth/password-reset` | Request password reset |
| `/password-reset` | Set new password (from email link) |
| `/auth/verify` | MFA challenge (when required) |

## Quick Start: Protect a Page

Use `getSession()` in React Server Components to check authentication:

```typescript
import { redirect } from 'next/navigation';
import { getSession } from '@kit/better-auth/context';

async function ProtectedPage() {
  const session = await getSession();

  if (!session) {
    redirect('/auth/sign-in');
  }

  return <div>Welcome, {session.user.name}</div>;
}
```

The function is cached per request using React's `cache()`. Multiple calls in the same request are efficient with no duplicate database queries.

For pages that need organization context with automatic redirects, use `getAccountContext()`:

```typescript
import { getAccountContext } from '@kit/better-auth/context';

async function DashboardPage() {
  // Redirects to sign-in if unauthenticated
  const context = await getAccountContext();

  return <div>Hello, {context.user.name}</div>;
}
```

See [Session Handling](./session-handling) for complete details on protecting routes.

## Common Pitfalls

- **Forgetting to check session in server components**: Proxy protection is a first gate, not the only gate. Always verify with `getSession()` in components that render user-specific data.
- **Using `getSession()` in client components**: It's server-only. Use `authClient.useSession()` for client components.
- **Not handling the loading state**: `useSession()` returns `isPending: true` initially. Show a skeleton or spinner to avoid layout shift.
- **Mixing up `getSession` and `getAccountContext`**: Use `getSession()` for basic auth checks; use `getAccountContext()` when you need organization context with auto-redirect.
- **Not testing the full auth flow**: Sign up, verification email, click link, sign in, access app. Test the entire chain before shipping.
- **Magic link bypasses MFA**: Users signing in with magic links skip the TOTP challenge. If MFA is critical for security, consider disabling magic links.

{% faq
   title="Frequently Asked Questions"
   items=[
     {"question": "Where are the sign-in and sign-up forms?", "answer": "The forms are in packages/auth/src/components/. They use @kit/ui components and read environment variables to show/hide auth methods. Customize them directly with React and Tailwind CSS."},
     {"question": "How do I add a new OAuth provider like GitHub or Apple?", "answer": "Configure the provider in packages/better-auth/src/plugins/social-providers.ts and add credentials to .env.local. See the Social Providers documentation for step-by-step setup."},
     {"question": "Can I require email verification before sign-in?", "answer": "Yes, and it's enabled by default. Users must verify their email before accessing the app. This prevents account takeover via email typos."},
     {"question": "How do I enable MFA for users?", "answer": "MFA support is already wired in. Users enable TOTP from their security settings at /settings/security and scan a QR code with an authenticator app like Google Authenticator or Authy."},
     {"question": "What happens when a session expires?", "answer": "The user is redirected to sign-in on the next request. Sessions are stored in the database via Prisma with configurable expiration (default 7 days)."},
     {"question": "How is auth state persisted?", "answer": "Better Auth stores session tokens in HTTP-only cookies and session data in your PostgreSQL database via Prisma. This allows session invalidation across devices."}
   ]
/%}

---

**Next:** [Sign In](./sign-in)
