KeyloomKeyloom
Keyloom Auth is currently in beta. Feedback and contributions are welcome!
Security

Security

Security model and best practices - cookies, JWT, OAuth, and CSRF.

Security

Keyloom provides a secure baseline and flexible options. This page summarizes the model and best practices.

Cookies

  • Set secure: true in production and use HTTPS
  • Prefer sameSite: lax for app UIs; use none only when needed for cross-site flows
  • Use domain and path to scope tokens if you host multiple apps

JWT strategy

  • Stateless verification using authSecret or JWKS
  • Good fit for edge runtimes and horizontal scaling
  • Consider short TTLs with rolling sessions for better UX

Database strategy

  • Server-side session store via adapter
  • Supports invalidation and introspection
  • Use when you need central control or long-lived sessions

OAuth providers

  • Use state and PKCE where supported
  • Rotate client secrets and limit scopes
  • Host callback endpoints on HTTPS only

CSRF

  • For Cookie-based APIs, prefer same-site cookies and CSRF tokens for unsafe methods
  • Middleware helps ensure protected routes require a valid session
  • cookie.secure: true
  • cookie.sameSite: "lax"
  • Distinct AUTH_SECRET per environment
  • Use HTTPS and HSTS
  • Limit provider scopes to what you need

Prerequisites

  • HTTPS enabled in all environments (use HSTS in production)
  • Strong AUTH_SECRET (32+ random bytes) stored in secret manager
  • Accurate NEXT_PUBLIC_APP_URL and cookie domain/path

Production hardening checklist

  • HTTPS enforced and HSTS set (max-age >= 15552000)
  • Secure cookies (secure: true, httpOnly: true, sameSite: 'lax')
  • CSP configured (script-src 'self' with hashes/nonces)
  • Rate limiting on auth endpoints
  • Provider scopes minimized and secrets rotated
  • CSRF protection on unsafe methods (POST/PUT/PATCH/DELETE)
  • JWT keys rotated regularly; JWKS public only
  • Logging/monitoring with redaction of PII and secrets
keyloom.config.ts
export default defineKeyloom({
  cookie: {
    name: "__keyloom",
    secure: process.env.NODE_ENV === "production",
    sameSite: "lax",
    httpOnly: true,
    domain: process.env.COOKIE_DOMAIN, // e.g. .example.com
    path: "/",
  },
});
  • Use sameSite: 'none' only when you truly need cross-site cookies
  • Scope domain minimally; avoid sharing across unrelated subdomains

CSRF protection examples

  • Use provided GET /api/auth/csrf and include token for unsafe methods
Client fetch with CSRF
const token = (await fetch("/api/auth/csrf").then((r) => r.json())).token;
await fetch("/api/secure/action", {
  method: "POST",
  headers: { "x-csrf-token": token },
});
Server verify (pattern)
export async function POST(req: Request) {
  const token = req.headers.get("x-csrf-token");
  if (!token) return Response.json({ error: "csrf" }, { status: 403 });
  // optionally compare to cookie or server store
  return Response.json({ ok: true });
}

OAuth provider scope guidance

  • Request only minimal scopes needed (e.g., read:user instead of full user)
  • Rotate client secrets periodically; store in secret manager
  • Verify state/PKCE; reject callbacks with mismatched state
  • Ensure callback URLs exactly match provider app configuration

Input validation and sanitization

  • Validate request bodies and params using a schema validator
Example with Zod
import { z } from "zod";

const CreateInput = z.object({
  name: z.string().min(1),
  email: z.string().email(),
});
export async function POST(req: Request) {
  const json = await req.json().catch(() => null);
  const parse = CreateInput.safeParse(json);
  if (!parse.success)
    return Response.json({ error: "invalid_request" }, { status: 400 });
  // proceed with safe data
}
  • Always encode untrusted output; avoid directly injecting user content into HTML

Deployment security considerations

  • Enforce HTTPS at the platform layer (Vercel: Redirects, HSTS header)
  • Set security headers: Strict-Transport-Security, Content-Security-Policy, X-Frame-Options, Referrer-Policy
  • Keep runtime up-to-date and enable automatic dependency updates where safe

Monitoring and logging

  • Log auth events (sign-in, sign-out, errors) with request IDs; avoid sensitive data
  • Alert on unusual patterns (failed logins surge, multiple org switches)
  • Redact tokens, cookies, and secrets from logs

Troubleshooting

  • Cookies not sent: check domain, path, sameSite, HTTPS, and subdomain usage
  • CSRF errors: ensure token included and same-site rules align with your flow
  • OAuth failures: confirm provider scopes, client ID/secret, and exact callback URL

See also

Next steps

  • Review provider scopes per integration and rotate secrets
  • Add rate limiting and security headers to your deployment

How is this guide?