# Auth Reference: Super Admin Login (OAuth2 PKCE via Janus)

## Full OAuth2 PKCE flow

```
LoginPage
  → generates code_verifier + code_challenge (SHA-256, base64url)
  → stores the verifier in sessionStorage[PKCE_VERIFIER_KEY]
  → redirects to: GET {VITE_JANUS_URL}/oauth2/authorize?...&continue

Janus → Google → login → redirects to /callback?code=XXX

CallbackPage
  → reads code from the URL + verifier from sessionStorage
  → POST {VITE_JANUS_URL}/oauth2/token (form-urlencoded, no proxy)
  → receives { access_token }
  → stores the token in sessionStorage[auth_token] via AuthContext
  → navigates to /
```

## Critical gotchas

- Trailing `&continue` on the authorize URL is **mandatory** — without it Janus returns 401
- The token exchange goes **directly** to Janus, not through a proxy (PKCE has no secret to protect)
- The app **must run on port 3000** — the redirect URI registered in Janus is `http://localhost:3000/callback`
- Use `bun run dev` (Vercel dev on 3000), NOT `npx vite` directly

## Key files

| File | Role |
|------|------|
| `src/providers/AuthContext.tsx` | React context — holds `accessToken`, `isAuthenticated`, `login()`, `logout()` |
| `src/pages/Auth/Login/constants.ts` | PKCE constants: `PKCE_VERIFIER_KEY`, `CODE_CHALLENGE_METHOD` |
| `src/pages/Auth/Login/index.tsx` | Generates verifier/challenge, redirects to Janus authorize |
| `src/pages/Auth/Callback/index.tsx` | Exchanges code for token, stores in context + sessionStorage |

## Auth-type marker

`src/App.tsx` is tagged with `// @humand-auth: super-admin` on line 1 so conflict detection can identify which auth stack is installed.

## Env vars

| Variable | Description | Example |
|----------|-------------|---------|
| `VITE_JANUS_URL` | Janus base URL | `https://api.humand.co/api/v1/janus` |
| `VITE_CLIENT_ID` | Client ID registered in Janus | `your-janus-client-id` |
