Getting Started
Installation
Section titled “Installation”bun add ideal-authnpm install ideal-authpnpm add ideal-authyarn add ideal-auth-
Generate a secret
Section titled “Generate a secret”ideal-auth requires a secret of at least 32 characters for encrypting sessions and signing tokens. Generate one with the built-in CLI:
Terminal window bunx ideal-auth secretAdd the output to your environment variables:
.env IDEAL_AUTH_SECRET="your-generated-secret-here" -
Create the cookie bridge
Section titled “Create the cookie bridge”The cookie bridge is what makes ideal-auth framework agnostic. It is an object with three functions —
get,set, anddelete— that tell ideal-auth how to interact with cookies in your framework.Here is a cookie bridge for Next.js (App Router):
lib/auth.ts import { cookies } from 'next/headers';import { createAuth, createHash } from 'ideal-auth';const cookieBridge = {async get(name: string) {const jar = await cookies();return jar.get(name)?.value;},async set(name: string, value: string, options: any) {const jar = await cookies();jar.set(name, value, options);},async delete(name: string) {const jar = await cookies();jar.delete(name);},}; -
Create the auth and hash instances
Section titled “Create the auth and hash instances”lib/auth.ts import { db } from './db'; // your database clientexport const hash = createHash();export const auth = createAuth({secret: process.env.IDEAL_AUTH_SECRET!,cookie: cookieBridge,// Look up a user by ID (used to rehydrate sessions)resolveUser: async (id) => {return db.user.findUnique({ where: { id } });},// Look up a user by credentials (used by auth().attempt())resolveUserByCredentials: async (credentials) => {return db.user.findUnique({ where: { email: credentials.email } });},// Provide the hash instance so attempt() can verify passwordshash,});createAuthreturns a factory function. Callauth()in each request to get a freshAuthInstancescoped to that request’s cookies. -
Implement login
Section titled “Implement login”app/login/actions.ts 'use server';import { auth } from '@/lib/auth';import { redirect } from 'next/navigation';export async function login(formData: FormData) {const email = formData.get('email') as string;const password = formData.get('password') as string;const success = await auth().attempt({ email, password });if (!success) {return { error: 'Invalid email or password.' };}redirect('/dashboard');}The
attemptmethod strips the password from the credentials, passes the remaining fields toresolveUserByCredentials, then verifies the password hash automatically. -
Implement logout
Section titled “Implement logout”app/logout/actions.ts 'use server';import { auth } from '@/lib/auth';import { redirect } from 'next/navigation';export async function logout() {await auth().logout();redirect('/login');} -
Protect routes with middleware
Section titled “Protect routes with middleware”middleware.ts import { NextResponse } from 'next/server';import type { NextRequest } from 'next/server';import { auth } from '@/lib/auth';export async function middleware(request: NextRequest) {const isAuthenticated = await auth().check();if (!isAuthenticated) {return NextResponse.redirect(new URL('/login', request.url));}return NextResponse.next();}export const config = {matcher: ['/dashboard/:path*', '/settings/:path*'],};
Registering users
Section titled “Registering users”ideal-auth does not manage user creation — that is up to your application. Use the hash instance to hash passwords before storing them:
'use server';
import { auth, hash } from '@/lib/auth';import { db } from '@/lib/db';import { redirect } from 'next/navigation';
export async function register(formData: FormData) { const email = formData.get('email') as string; const password = formData.get('password') as string;
const hashedPassword = await hash.make(password);
const user = await db.user.create({ data: { email, password: hashedPassword }, });
// Log the user in immediately after registration await auth().login(user);
redirect('/dashboard');}Reading the current user
Section titled “Reading the current user”Use auth().user() to get the full user object, or auth().id() to get just the user ID:
const currentUser = await auth().user(); // TUser | nullconst userId = await auth().id(); // string | nullNext steps
Section titled “Next steps”- Configuration — All configuration options in detail
- Two-Factor Authentication — Add TOTP 2FA to your app
- Rate Limiting — Protect login endpoints from brute force
- Security Model — Understand the security guarantees