Auth Setup Guide

This guide describes how to add and configure authentication for the Operyn dashboard. It assumes you are following the plan: better-auth in the Next.js dashboard, with SSO (Google, GitHub), organization plugin, and optional RBAC, in a modular way that can later be moved to a dedicated auth service.

Prerequisites

  • Existing Operyn monorepo with dashboard and Postgres (same DB used by services).
  • Environment variables for Postgres (e.g. DATABASE_URL or POSTGRES_*) available to the dashboard app.

Concepts

Implementation Order (high level)

  1. Dependencies and database — Add better-auth, @better-auth/drizzle-adapter, and plugin packages. Add a Drizzle client for the dashboard (e.g. lib/auth/db.ts) using the same Postgres. Run npx auth@latest generate and apply migrations (optionally in a dedicated auth schema).
  2. Auth config and API route — Implement the central auth config (Drizzle adapter, Google, GitHub, email/password, organization plugin, optional RBAC). Add the auth client config. Add app/api/auth/[...all]/route.ts that delegates to the better-auth handler.
  3. Auth feature and routes — Add sign-in and sign-up pages under a marketing or auth route group. Add a session provider and, if using the organization plugin, an org switcher. Protect /console via middleware (redirect unauthenticated users to /login).
  4. Organization and RBAC usage — Create a default organization on first login if needed. Add organization (and team) management under Settings. Implement permission checks (e.g. a small can(session, 'remediation:approve') helper) using the role–permission matrix.
  5. Backend JWT (optional) — Define JWT payload in @operyn/shared-types. Have the dashboard send a JWT when calling Incident Engine and Remediation Engine. Add a JWT guard in each NestJS service to validate the token and attach user context.

Environment Variables (dashboard)

Typical variables for auth:

VariableDescription
DATABASE_URLPostgres connection string (or build from POSTGRES_HOST, POSTGRES_USER, etc.).
BETTER_AUTH_SECRETSecret for signing sessions; use a long random string in production.
BETTER_AUTH_URLBase URL of the dashboard (e.g. http://localhost:3000 for dev).
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRETFor Google sign-in (optional).
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRETFor GitHub sign-in (optional).

For local bun dev with Docker Compose, the minimum you need is:

  • Postgres connectivity for the dashboard (DATABASE_URL or POSTGRES_HOST + credentials from root .env)
  • BETTER_AUTH_SECRET
  • BETTER_AUTH_URL
  • BETTER_AUTH_TRUSTED_ORIGINS (so Better Auth can verify callback/origin safely)

For enterprise SSO (OIDC/SAML), additional variables are required; see better-auth SSO plugin documentation.

File Layout (dashboard)

  • lib/auth/config.ts — Single betterAuth({ ... }) instance (database, providers, organization, RBAC).
  • lib/auth/db.ts — Drizzle client for auth tables.
  • lib/auth/client.tscreateAuthClient(...) for the browser.
  • app/api/auth/[...all]/route.ts — Thin handler delegating to better-auth.
  • features/auth/components/ — Sign-in, sign-up, session provider, org switcher.
  • middleware.ts — Protect /console, allow /, /login, /sign-up, /api/auth/*.

After Setup

  • Configure at least one sign-in method (email/password or a social provider).
  • Create or join an organization so users have an org context.
  • Use the roles and permissions matrix to gate UI and, if needed, backend endpoints.