Skip to content

feat(ui): migrazione auth frontend a OIDC/PKCE — rimosso Clerk (#235 Fase 6) - #241

Merged
gzileni merged 1 commit into
mainfrom
feat/frontend-oidc-235
Jul 21, 2026
Merged

feat(ui): migrazione auth frontend a OIDC/PKCE — rimosso Clerk (#235 Fase 6)#241
gzileni merged 1 commit into
mainfrom
feat/frontend-oidc-235

Conversation

@gzileni

@gzileni gzileni commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Fase 6: il frontend passa da @clerk/nextjs a 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=create per la registrazione. Token in localStorage, verifier/state in sessionStorage.
  • lib/auth.tsxAuthProvider + useAuth + helper dichiarativi (SignedIn/SignedOut/SignInButton/SignUpButton) che sostituiscono la superficie Clerk. Fallback no-auth quando NEXT_PUBLIC_OIDC_* non è impostata (modalità dev, come AUTH_ENABLED=false sul backend).
  • SiteHeaderUserButton Clerk → UserMenu custom (dropdown controllato, nessuna dipendenza da Bootstrap JS).
  • /login, /sign-in, /sign-up — redirect all'IdP (Keycloak ospita login/registrazione, incluso SPID).
  • Rimosso @clerk/clerk-react (package.json + lockfile). Nuove env NEXT_PUBLIC_OIDC_AUTHORITY/CLIENT_ID/SCOPE.
  • Docs (R14): README (riga auth + tabella componenti), privacy (IdP self-hosted, nessun sub-processor extra-UE), env examples, api-keys.

Verifica

tsc --noEmit pulito · next build static export 27 pagine OK · next lint senza errori (solo warning preesistenti). Deve puntare allo stesso issuer di OIDC_ISSUER del backend.

⚠️ Il giro OIDC end-to-end va verificato con un Keycloak reale (redirect, scambio token, refresh) — qui è validato a livello di build/tipi. Registrare https://<host>/* come redirect URI valido sul client Keycloak.

Restano (issue #235)

  • Fase 4 — UI dashboard admin /admin (consuma /admin/users).
  • Fase 5 — schermate registrazione SPID + email-OTP a tema su Keycloak.

Parte di #235.

🤖 Generated with Claude Code

…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>
@gzileni
gzileni merged commit 9853350 into main Jul 21, 2026
27 checks passed
@gzileni
gzileni deleted the feat/frontend-oidc-235 branch July 21, 2026 14:20

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +19 to +20
const AUTHORITY = (process.env.NEXT_PUBLIC_OIDC_AUTHORITY ?? "").replace(/\/+$/, "");
const CLIENT_ID = process.env.NEXT_PUBLIC_OIDC_CLIENT_ID ?? "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +77 to +79
const getToken = useCallback(
async () => (authConfigured ? await oidc.getAccessToken() : null),
[],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant