pvm/docs/TODO_SECURITY.md
Mikkel Georgsen 76489a53a6 Add social login providers (Google, Apple, Facebook) to TODO
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 12:57:19 +01:00

2.7 KiB

Security & Technical Debt

Items identified during code review that should be addressed before production.

High Priority

Token refresh logic in SvelteKit (apps/dashboard/src/auth.ts)

The JWT callback stores expiresAt and refreshToken but never checks expiry or initiates a refresh. Auth.js does not auto-refresh tokens. Without this, users get silently logged out when their access token expires (typically 5-15 minutes for Zitadel).

Fix: Add expiry check in the jwt callback and use refreshToken to obtain a new access token when expired.

JWKS cache thundering herd (crates/pvm-auth/src/jwks.rs)

When the cache expires, every concurrent request sees stale cache and calls refresh() simultaneously. The RwLock serializes writes but each request still makes an HTTP call before acquiring the lock.

Fix: Add a "refresh-in-progress" flag or use double-checked locking so only one request triggers the refresh while others wait.

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

trustHost: true in auth.ts

Disables CSRF origin check in Auth.js. Required for local dev behind localhost, but must be removed or made conditional for production.

devMode: true in OIDC app config (docker/setup-zitadel.sh)

Disables redirect URI validation in Zitadel. The setup script is dev-only, but if a similar script is used for production, this must be false.

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.

Low Priority

Shell script JSON parsing (docker/setup-zitadel.sh)

Uses grep -o and cut to extract JSON fields. Fragile if JSON format changes. Consider using jq with a fallback.

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.