feat(ui): migrazione auth frontend a OIDC/PKCE — rimosso Clerk (#235 Fase 6) - #241
Conversation
…ase 6) Il frontend (static export, R6) autentica via OIDC Authorization-Code + PKCE contro un IdP self-hostable (Keycloak — SPID + registrazione email-OTP), senza SDK proprietario. Progetto open source ospitato da ogni Regione → niente lock-in Clerk. - lib/oidc.ts: client OIDC dependency-free (discovery, PKCE S256, refresh, logout RP-initiated, prompt=create per la registrazione). Solo fetch + Web Crypto. - lib/auth.tsx: AuthProvider + useAuth + helper dichiarativi (SignedIn/SignedOut/ SignInButton/SignUpButton). Fallback no-auth quando NEXT_PUBLIC_OIDC_* non impostate (modalità dev, come AUTH_ENABLED=false lato backend). - SiteHeader: UserButton Clerk → UserMenu custom (dropdown controllato, no bootstrap JS). - login/sign-in/sign-up: redirect all'IdP (Keycloak ospita le schermate). - Rimosso @clerk/clerk-react (package.json + lock). Env NEXT_PUBLIC_OIDC_*. - Docs: README (auth OIDC), privacy (IdP self-hosted, no processor extra-UE), api-keys. tsc + next build (27 pagine) + lint OK. Il giro OIDC live va verificato con un Keycloak reale. Restano Fase 4 (UI dashboard admin) e Fase 5 (schermate registrazione). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 620d901511
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const AUTHORITY = (process.env.NEXT_PUBLIC_OIDC_AUTHORITY ?? "").replace(/\/+$/, ""); | ||
| const CLIENT_ID = process.env.NEXT_PUBLIC_OIDC_CLIENT_ID ?? ""; |
There was a problem hiding this comment.
Pass OIDC build args into static UI images
When the UI is built through the existing Docker paths, these new NEXT_PUBLIC_OIDC_* values are never baked into the Next static bundle: I checked opendata-ai-ui/Dockerfile:18-25, docker-compose.yml:548-552, and .github/workflows/docker-publish.yml:154-158, and they still forward only the old Clerk args. Because oidcConfigured is computed from these build-time constants, Docker-built production images will compile with auth disabled even when deployment envs contain the OIDC issuer/client, so protected UI runs in dev/no-auth mode and API calls omit bearer tokens.
Useful? React with 👍 / 👎.
| const getToken = useCallback( | ||
| async () => (authConfigured ? await oidc.getAccessToken() : null), | ||
| [], |
There was a problem hiding this comment.
Clear auth state when token refresh fails
When a session expires or the refresh token is revoked, oidc.getAccessToken() clears storage and returns null, but this getToken wrapper does not update the provider's user state. In that expired-session context, <SignedIn> and DashboardGate keep treating the user as authenticated while subsequent API calls silently drop the Authorization header, leaving the user stuck on protected pages with 401s until a full reload.
Useful? React with 👍 / 👎.
Fase 6: il frontend passa da
@clerk/nextjsa un'autenticazione OIDC self-hostable, così ogni Regione può ospitarlo con il proprio IdP (Keycloak — SPID + registrazione email-OTP) senza lock-in su un SaaS.Come
Static export (R6): nessun server → OIDC Authorization-Code + PKCE lato browser, dependency-free (solo
fetch+ Web Crypto), niente SDK proprietario.lib/oidc.ts— discovery/.well-known/openid-configuration, PKCE S256, scambio code→token, refresh, logout RP-initiated,prompt=createper la registrazione. Token inlocalStorage, verifier/state insessionStorage.lib/auth.tsx—AuthProvider+useAuth+ helper dichiarativi (SignedIn/SignedOut/SignInButton/SignUpButton) che sostituiscono la superficie Clerk. Fallback no-auth quandoNEXT_PUBLIC_OIDC_*non è impostata (modalità dev, comeAUTH_ENABLED=falsesul backend).SiteHeader—UserButtonClerk →UserMenucustom (dropdown controllato, nessuna dipendenza da Bootstrap JS)./login,/sign-in,/sign-up— redirect all'IdP (Keycloak ospita login/registrazione, incluso SPID).@clerk/clerk-react(package.json + lockfile). Nuove envNEXT_PUBLIC_OIDC_AUTHORITY/CLIENT_ID/SCOPE.Verifica
tsc --noEmitpulito ·next buildstatic export 27 pagine OK ·next lintsenza errori (solo warning preesistenti). Deve puntare allo stesso issuer diOIDC_ISSUERdel backend.https://<host>/*come redirect URI valido sul client Keycloak.Restano (issue #235)
/admin(consuma/admin/users).Parte di #235.
🤖 Generated with Claude Code