# Athena Auth Next.js + HeroUI Demo

This is a real demo UI wired to the Better Auth JS SDK.

Primary backend onboarding docs live at:

- `../../runbooks/ONBOARDING.md`
- `../../runbooks/TROUBLESHOOTING.md`
- `./docs/ui-component-architecture.md`
- `./docs/proxy-upstream-and-trusted-origins.md`

## 1) Start athena-auth server

From repo root:

```bash
docker compose up -d postgres
cargo run --bin server --features server
```

## 2) Start the Next.js app

```bash
cd apps/demo
pnpm install
pnpm dev
```

Open `http://localhost:3001/login` (or whatever port Next picks).

## Environment

Create `apps/demo/.env.local`:

```env
ATHENA_AUTH_ORIGIN=http://localhost:3000
# Optional multi-domain host map:
# ATHENA_AUTH_ORIGIN_MAP=athena-auth-*-suits-finance.vercel.app=https://auth.athena-cluster.com
NEXT_PUBLIC_AUTH_BASE_URL=http://localhost:3000
NEXT_PUBLIC_AUTH_BASE_PATH=/api/auth
NEXT_PUBLIC_AUTH_SOCIAL_PROVIDERS=google,github,cloudflare,discord
NEXT_PUBLIC_AUTH_SOCIAL_CALLBACK_PATH=/session
TRUSTED_ORIGINS=http://localhost:3001,http://localhost:3000,https://app.formations.company,https://speedrun-formations.vercel.app,https://suits-finance-*-athena-auth.vercel.app,https://*.vercel.app
# Optional multi-domain upstream override (incoming host -> upstream auth origin)
# ATHENA_AUTH_ORIGIN_MAP=athena-auth-*-suits-finance.vercel.app=https://auth.athena-cluster.com

# Optional diagnostics-only readiness checks in the Next.js runtime
# (booleans are shown in UI; values are never returned)
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
CLOUDFLARE_CLIENT_ID=
CLOUDFLARE_CLIENT_SECRET=
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
```

Upstream resolution order is:

1. `ATHENA_AUTH_ORIGIN_MAP` host match (if configured)
2. `ATHENA_AUTH_ORIGIN`
3. `NEXT_PUBLIC_AUTH_BASE_URL`
4. `http://localhost:3000` only when `NODE_ENV != production`

The Next.js API proxy receives `/api/auth/*` on the frontend and forwards to the Rust server root (`/`).
`TRUSTED_ORIGINS` is also read by the Next.js proxy for CORS preflight handling and supports exact origins, URL-shaped patterns, and bare-host `*` wildcard globs. Bare non-local hosts infer `https://`, so `*.vercel.app` is matched as `https://*.vercel.app`.
`ATHENA_AUTH_ORIGIN` (or `NEXT_PUBLIC_AUTH_BASE_URL`) is the proxy upstream target and must be a concrete URL (no `*`).
When the proxy forwards `/api/auth/<path>`, the primary upstream request is always `/<path>` (root-based); `/api/auth/<path>` is only used as a fallback path on upstream 404.
`ATHENA_AUTH_ORIGIN_MAP` can be used when one deployment serves multiple incoming hostnames that should resolve to different concrete upstream auth origins; the map key is normalized to the host pattern before matching.
In deployed environments, the upstream host must be publicly reachable (do not use `localhost`, `127.*`, `10.*`, `192.168.*`, etc.).
Social login buttons only render for providers listed in `NEXT_PUBLIC_AUTH_SOCIAL_PROVIDERS` **and** marked ready by diagnostics (provider `*_CLIENT_ID` + `*_CLIENT_SECRET` presence).
Tenant routing can be set from the login page controls; the demo stores tenant id/header in local storage and proxy cookies, then forwards that header upstream.

## Pages

- `/login`
- `/sign-up`
- `/forgot-password`
- `/session`
- `/endpoint-lab`
- `/organizations`
- `/schema-debug`

The forms call Better Auth SDK methods:

- `authClient.signIn.email`
- `authClient.signUp.email`
- `authClient.requestPasswordReset`
- `authClient.signIn.social` (only for configured providers)
- `authClient.useSession`
- `authClient.signOut`

Organizations page calls the auth routes directly (same-origin `/api/auth/*`) to exercise:

- organization creation/listing and active org switching
- member invitation flow
- list org invitations
- list user invitations
- accept/decline/cancel invitation flows
- list/update/remove members
- invitation-coupled email evidence lookups
- API key create/list/delete for current authenticated user
- preflight RBAC guards (active org + membership role) that disable invalid actions before request-time

Endpoint lab page exercises endpoint-level coverage templates for:

- session revoke/list flows
- OAuth account/link/token probe flows
- passkey option/verify/list/mutation flows
- organization CRUD and invitation/member/permission probe flows

Endpoint lab workflow:

- Use `Autofill from live data` to hydrate context (`organizationId`, `invitationId`, `memberId`, `sessionToken`, `providerId`, `accountId`, `passkeyId`) from real API responses.
- Use `Run full suite` for all listed endpoints or run per-group/per-endpoint from the matrix.
- Destructive endpoints are skipped by default and can be included explicitly with the destructive toggle.
- Each endpoint row shows:
  - resolved path with current context values
  - missing required context fields (if any)
  - last run state (`ok`, `error`, `skipped`, `not run`) and HTTP status
- Request history stores detailed response snapshots to verify behavior endpoint-by-endpoint.

Diagnostics shown in UI:

- Forgot-password status is split into:
  - request acceptance by API
  - delivery caveat (mail transport required; acceptance alone does not prove inbox delivery)
- Runtime docs/admin config endpoints are intentionally disabled in this repo build.
- `/api/auth/diagnostics` now exposes a social-provider readiness matrix (enabled list, client id set, client secret set, ready).
- Runtime fallback mode retries direct auth endpoints when extension/runtime interference breaks SDK submit/resend flows.
- Session/org/email views refresh automatically (30s interval + focus), with no manual refresh buttons.
- Tenant routing context is editable from the auth controls (`tenant id` + `header name`) and is forwarded by `/api/auth/*` proxy handlers.

## Debug pages

Use these pages/routes when auth wiring is wrong and you need the exact failure instead of a generic "wrong origin" guess:

- Demo schema/origin page: `http://localhost:3001/schema-debug`
  - Pulls `GET /api/auth/debug/schema` through the Next.js app.
  - Shows proxy upstream resolution, runtime config, tenant resolution, and trusted-origin diagnostics.
  - When a request is rejected by origin policy, the page shows recent rejected attempts, what origin/referer was delivered, what the server expected, and a suggested `TRUSTED_ORIGINS=...` line to add.
- Rust server schema debug route: `http://localhost:3000/debug/schema`
  - Direct server-side view of the same runtime/debug payload.
  - Includes `origin_rejection_debug` for recent server-side rejects.
- Rust metrics endpoint: `http://localhost:3000/metrics`
  - Prometheus scrape target.
- Rust metrics dashboard: `http://localhost:3000/metrics/view`
  - HTML dashboard for quick operator checks without Prometheus/Grafana.

Recommended local debugging flow:

1. Open `/schema-debug`.
2. Reproduce the auth request that failed.
3. Check whether the failure is upstream resolution or `TRUSTED_ORIGINS`.
4. If it is an origin reject, copy the suggested allowlist entry into both `apps/demo/.env.local` and the Rust server `.env`.
5. Restart both processes and retry.

## Common issues

- `404 /api/auth/*`: ensure server is running and `AUTH_BASE_PATH=/` on Rust when using the Next.js proxy.
- Verify-email not working: verification links must pass through `/api/auth/verify-email` first, then redirect via `callbackURL`. When Rust is mounted at `/`, set `PUBLIC_AUTH_BASE_PATH=/api/auth`.
- CORS/preflight failures: open `/schema-debug`, reproduce the request, and use the trusted-origin rejection section to see the delivered origin plus the exact `TRUSTED_ORIGINS` entry you need in both `apps/demo/.env.local` and the Rust server `.env`.
