- 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>
2.3 KiB
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.
- Google — Google Cloud Console OAuth 2.0 Client ID
- Apple — Apple Developer Sign in with Apple service ID + key
- 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)
trustHost: trueChanged to trustHost: dev — uses SvelteKit's $app/environment to enable only in dev mode.
devMode: true (done)
devMode: trueMade 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.