Login (OAuth + PKCE)
ScaiCrew uses a backend-orchestrated OAuth Authorization-Code + PKCE flow against ScaiKey's platform OIDC. The browser never touches the token endpoint — the backend is the confidential client and mints its own session token once login succeeds.
The flow#
| Step | Endpoint | What happens |
|---|---|---|
| 1 | POST /v1/auth/login |
Backend creates state + PKCE, stashes them, returns ScaiKey's authorize URL. |
| 2 | (browser) | The SPA redirects to ScaiKey; the user authenticates. |
| 3 | GET /v1/auth/callback |
ScaiKey redirects here; the backend exchanges the code (with the client secret + PKCE verifier), resolves the user's workspaces, and bounces the browser to the SPA with a one-shot session_code. |
| 4 | POST /v1/auth/token |
The SPA redeems the session_code. One workspace → a session token; many → a requires_selection list, then a second call with the chosen workspace_id. |
| 5 | POST /v1/auth/refresh |
Re-mints a session token from the refresh token, re-reading the role from the database so grant changes take effect without re-login. Also how workspace switching works. |
The session token#
The token the SPA presents to /v1 on every call is ScaiCrew's own HS256 token, not ScaiKey's.
It carries the resolved (subject, tenant, workspace, role), so the API reads scope and role
directly from the verified token — no per-request membership lookup. The middleware verifies this
token first and falls back to ScaiKey's JWKS for service / per-member tokens.
App registration#
The backend authenticates as a GLOBAL confidential WEB app in ScaiKey (the same app used for
service-to-service client_credentials). It must have:
- the OAuth callback registered as a redirect URI (e.g.
https://<host>/v1/auth/callback), - the
authorization_codeandrefresh_tokengrants, - the
openid profile emailscopes.
Dev mode#
For local development without OIDC, the backend accepts X-Dev-Workspace-Id / X-Dev-Subject /
X-Dev-Role headers instead of a bearer token. This path is only active when the service runs
with ENV=dev; in production it is disabled entirely.