Skip to content

Getting Started

Terminal window
bun add ideal-auth
  1. 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 secret

    Add the output to your environment variables:

    .env
    IDEAL_AUTH_SECRET="your-generated-secret-here"
  2. The cookie bridge is what makes ideal-auth framework agnostic. It is an object with three functions — get, set, and delete — 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);
    },
    };
  3. lib/auth.ts
    import { db } from './db'; // your database client
    export 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 passwords
    hash,
    });

    createAuth returns a factory function. Call auth() in each request to get a fresh AuthInstance scoped to that request’s cookies.

  4. 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 attempt method strips the password from the credentials, passes the remaining fields to resolveUserByCredentials, then verifies the password hash automatically.

  5. 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');
    }
  6. 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*'],
    };

ideal-auth does not manage user creation — that is up to your application. Use the hash instance to hash passwords before storing them:

app/register/actions.ts
'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');
}

Use auth().user() to get the full user object, or auth().id() to get just the user ID:

const currentUser = await auth().user(); // TUser | null
const userId = await auth().id(); // string | null