Authentication

Set up email and OAuth authentication with better-auth.

Authentication

This template uses better-auth for authentication. It supports email/password login and OAuth providers out of the box.

Overview

Authentication is pre-configured with:

  • Email + password sign-up and sign-in
  • OAuth (Google, GitHub)
  • Session management
  • Protected routes

Server-Side Usage

Use auth.api.getSession() in loaders and actions to check authentication:

import { auth } from "@/lib/auth";
import type { Route } from "./+types/my-route";

export async function loader({ request }: Route.LoaderArgs) {
  const session = await auth.api.getSession({
    headers: request.headers,
  });

  if (!session) {
    throw new Response(null, {
      status: 302,
      headers: { Location: "/login" },
    });
  }

  return { user: session.user };
}

Client-Side Usage

Use the auth client hooks in your components:

import { authClient } from "@/lib/auth-client";

// Sign in with email
await authClient.signIn.email({
  email: "[email protected]",
  password: "password123",
});

// Sign in with OAuth
await authClient.signIn.social({
  provider: "github",
});

// Sign out
await authClient.signOut();

Adding OAuth Providers

  1. Add your OAuth credentials to .env:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GITHUB_CLIENT_ID=your-client-id
GITHUB_CLIENT_SECRET=your-client-secret
  1. The providers are already configured in lib/auth.ts. Just add the environment variables and they'll work.

Session Management

Sessions are stored in the database and managed automatically by better-auth. Each session includes:

  • User ID
  • Session token
  • Expiration time
  • IP address and user agent

Protected Routes

To protect a route, check for a session in the loader:

export async function loader({ request }: Route.LoaderArgs) {
  const session = await auth.api.getSession({
    headers: request.headers,
  });

  if (!session) {
    throw new Response(null, {
      status: 302,
      headers: { Location: "/login" },
    });
  }

  return { user: session.user };
}

This pattern redirects unauthenticated users to the login page.