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
- 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
- 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.