- Add token refresh logic in Auth.js JWT callback with 60s expiry buffer - Fix JWKS cache thundering herd with Mutex + double-checked locking - Make trustHost conditional (dev-only) via SvelteKit's $app/environment - Make devMode conditional on ZITADEL_PRODUCTION env var in setup script - Replace fragile grep/cut JSON parsing with jq in setup-zitadel.sh - Add OIDC_GRANT_TYPE_REFRESH_TOKEN to Zitadel OIDC app grant types - Update TODO_SECURITY.md: mark resolved items, add RefreshAccessTokenError frontend handling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
47 lines
2.3 KiB
Markdown
47 lines
2.3 KiB
Markdown
# Security & Technical Debt
|
|
|
|
Items identified during code review that should be addressed before production.
|
|
|
|
## High Priority
|
|
|
|
### Social login providers (Zitadel IDP configuration)
|
|
Configure external identity providers in Zitadel so users can sign in with social accounts. Each requires creating OAuth2 credentials with the respective provider and registering them in Zitadel Console → Settings → Identity Providers.
|
|
|
|
1. **Google** — Google Cloud Console OAuth 2.0 Client ID
|
|
2. **Apple** — Apple Developer Sign in with Apple service ID + key
|
|
3. **Facebook** — Meta for Developers app with Facebook Login product
|
|
|
|
No code changes needed in the SvelteKit app — Zitadel's login page shows social buttons automatically once IDPs are configured.
|
|
|
|
## Medium Priority
|
|
|
|
### Custom login UI
|
|
Replace the default Zitadel login v1 UI with a fully custom login/signup flow built into the SvelteKit dashboard using Zitadel's Session API. Includes: login, signup, password reset, 2FA flows. Must match PVM visual design.
|
|
|
|
### Frontend handling of RefreshAccessTokenError
|
|
The session now exposes `session.error` when token refresh fails, but no frontend component checks this to redirect the user to `/login`. Add a check in the dashboard layout or a client-side hook.
|
|
|
|
## Low Priority
|
|
|
|
### PAT expiration
|
|
Machine user PAT expires 2030-01-01. Fine for dev, but production should use shorter-lived credentials.
|
|
|
|
### Running Zitadel as root (`docker-compose.dev.yml`)
|
|
`user: "0"` is required for `start-from-init` to write the PAT file. Dev-only concern — production deployment should use proper volume permissions.
|
|
|
|
## Resolved
|
|
|
|
### ~~Token refresh logic~~ (done)
|
|
Added expiry check + refresh in `auth.ts` JWT callback. Uses `refreshToken` to call Zitadel's token endpoint with `client_secret_basic`.
|
|
|
|
### ~~JWKS cache thundering herd~~ (done)
|
|
Added `tokio::sync::Mutex` refresh lock with double-checked locking in `jwks.rs`. Only one request triggers HTTP refresh; others wait.
|
|
|
|
### ~~`trustHost: true`~~ (done)
|
|
Changed to `trustHost: dev` — uses SvelteKit's `$app/environment` to enable only in dev mode.
|
|
|
|
### ~~`devMode: true`~~ (done)
|
|
Made conditional on `ZITADEL_PRODUCTION` env var in `setup-zitadel.sh`.
|
|
|
|
### ~~Shell script JSON parsing~~ (done)
|
|
Replaced all `grep -o`/`cut` with `jq -r` in `setup-zitadel.sh`. Added jq preflight check.
|