80 lines
3.4 KiB
Markdown
80 lines
3.4 KiB
Markdown
# Auth Rules
|
|
|
|
This repository keeps the current LLM-first CRUD generation architecture as the primary working baseline.
|
|
|
|
- Auth is part of the default generation path, not a post-generation addon.
|
|
- `server/` is the active backend target output path.
|
|
- `client/` is the active frontend target output path.
|
|
- The generated runtime stays SPA + API + external Keycloak + PostgreSQL only.
|
|
|
|
## Frontend auth invariants
|
|
|
|
- Use `keycloak-js` with redirect-based login only.
|
|
- Initialize Keycloak before rendering the SPA.
|
|
- Use Authorization Code Flow + PKCE (`S256`).
|
|
- Keep `authProvider`, `dataProvider`, `getIdentity()`, `getPermissions()`, and `checkError()` as stable provider seams.
|
|
- Derive identity from token claims already present in the parsed token.
|
|
- Do not call `loadUserProfile()` and do not depend on `/account` for the baseline app.
|
|
- `401` must force re-authentication; `403` must stay an authorization error.
|
|
- Keep token handling in memory and refresh through one shared in-flight operation.
|
|
|
|
## Working runtime defaults
|
|
|
|
Use the already working project defaults unless a prompt explicitly overrides them.
|
|
|
|
- Frontend Keycloak base URL example:
|
|
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
|
|
- Frontend realm and client example:
|
|
- `VITE_KEYCLOAK_REALM=toir`
|
|
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
|
|
- Backend issuer and audience example:
|
|
- `KEYCLOAK_ISSUER_URL=https://sso.greact.ru/realms/toir`
|
|
- `KEYCLOAK_AUDIENCE=toir-backend`
|
|
- CORS example:
|
|
- `CORS_ALLOWED_ORIGINS=http://localhost:5173,https://toir-frontend.greact.ru`
|
|
|
|
Anti-regression rule:
|
|
|
|
- Do not switch the baseline Keycloak example back to `http://localhost:8080` in generated `.env.example` files unless the prompt explicitly asks for a local Keycloak runtime.
|
|
- Localhost Keycloak values may exist in private `.env.local` or `.env` overrides, but they are not the default project examples.
|
|
|
|
## Backend auth invariants
|
|
|
|
- Verify JWTs with `jose`.
|
|
- Validate issuer + audience + signature via JWKS.
|
|
- Resolve JWKS in this order:
|
|
1. `KEYCLOAK_JWKS_URL`
|
|
2. OIDC discovery at `/.well-known/openid-configuration`
|
|
3. `${issuer}/protocol/openid-connect/certs`
|
|
- Extract roles only from `realm_access.roles`.
|
|
- Keep `/health` public and all generated CRUD routes protected by default.
|
|
|
|
## Auth anti-regression invariants
|
|
|
|
- The accepted JWKS resolution chain above is the only baseline truth path. Do not document one order and implement another.
|
|
- If auth implementation changes, `prompts/auth-rules.md` and `prompts/validation-rules.md` must be updated in the same change.
|
|
- Do not skip OIDC discovery when no explicit `KEYCLOAK_JWKS_URL` is provided.
|
|
- Do not switch role extraction to alternative claims unless the prompt explicitly changes the baseline contract.
|
|
- Do not reintroduce localhost Keycloak defaults into shared baseline examples.
|
|
|
|
## Realm artifact contract
|
|
|
|
- A physical root-level `*-realm.json` artifact is mandatory output.
|
|
- The artifact must be importable, versioned, and aligned with generated backend/frontend env contracts.
|
|
- It must parameterize:
|
|
- realm name
|
|
- frontend client id
|
|
- backend client id / audience
|
|
- local and production frontend URLs
|
|
- artifact filename
|
|
- It must explicitly deliver:
|
|
- `sub`
|
|
- `aud`
|
|
- `realm_access.roles`
|
|
- It must define:
|
|
- realm roles `admin`, `editor`, `viewer`
|
|
- a public SPA client with PKCE S256
|
|
- a bearer-only backend client
|
|
- an explicit audience client scope
|
|
- explicit protocol mappers for baseline identity and role claims
|