Avant : l'interface ne se protégeait que par une authentification HTTP Basic locale (AUTH_USER / AUTH_PASS), ou pas du tout.
Après : AUTH_MODE=oidc délègue la connexion à un fournisseur OpenID Connect (Keycloak, Authentik, Authelia…). Ouvrir l'interface renvoie vers la page de connexion du fournisseur puis revient sur la page demandée ; un bouton de déconnexion apparaît en haut à droite. AUTH_MODE=local (défaut) garde exactement le comportement actuel.
Comment
auth.go (nouveau) : Basic Auth déplacée depuis main.go sans changement ; client OIDC en Go standard, sans dépendance : découverte .well-known, flux authorization code + PKCE S256, state et nonce dans un cookie signé par connexion, échange du code (client_secret_basic, ou client_secret_post si le fournisseur n'accepte que lui), vérification de l'ID token (signature RS/PS/ES via JWKS avec rechargement à la rotation des clés, iss, aud, azp, exp, iat, nonce).
Session : cookie HttpOnly, SameSite=Lax, Secure si l'URL de retour est en https, signé HMAC avec une clé gardée dans /data/session.key (survit aux redémarrages), durée OIDC_SESSION_TTL (12h).
Non connecté : les pages redirigent vers le fournisseur, /api/* répond 401 {"code":"auth"} que l'UI transforme en rechargement (donc en reconnexion). /healthz reste ouvert.
Variables : AUTH_MODE, OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_REDIRECT_URL, plus OIDC_SCOPES et OIDC_SESSION_TTL optionnelles ; documentées dans .env.example, docker-compose.yml, README.md et README.fr.md (nouvelle section Authentification).
Tests (auth_test.go) : flux complet contre un faux fournisseur en mémoire (RS256 et ES256), refus d'un nonce, d'une audience, d'un issuer ou d'une expiration incorrects, callback forgé, cookie de session forgé, configuration incomplète.
Non testé : l'interface dans un navigateur et un vrai fournisseur (Keycloak/Authentik).
<!-- ccr-projects-attribution: {"github_login":"vblogio"} -->
_Requested by **Cédric**_
Avant : l'interface ne se protégeait que par une authentification HTTP Basic locale (`AUTH_USER` / `AUTH_PASS`), ou pas du tout.
Après : `AUTH_MODE=oidc` délègue la connexion à un fournisseur OpenID Connect (Keycloak, Authentik, Authelia…). Ouvrir l'interface renvoie vers la page de connexion du fournisseur puis revient sur la page demandée ; un bouton de déconnexion apparaît en haut à droite. `AUTH_MODE=local` (défaut) garde exactement le comportement actuel.
## Comment
- `auth.go` (nouveau) : Basic Auth déplacée depuis `main.go` sans changement ; client OIDC en Go standard, sans dépendance : découverte `.well-known`, flux authorization code + PKCE S256, `state` et `nonce` dans un cookie signé par connexion, échange du code (client_secret_basic, ou client_secret_post si le fournisseur n'accepte que lui), vérification de l'ID token (signature RS/PS/ES via JWKS avec rechargement à la rotation des clés, `iss`, `aud`, `azp`, `exp`, `iat`, `nonce`).
- Session : cookie HttpOnly, SameSite=Lax, Secure si l'URL de retour est en https, signé HMAC avec une clé gardée dans `/data/session.key` (survit aux redémarrages), durée `OIDC_SESSION_TTL` (12h).
- Non connecté : les pages redirigent vers le fournisseur, `/api/*` répond 401 `{"code":"auth"}` que l'UI transforme en rechargement (donc en reconnexion). `/healthz` reste ouvert.
- Variables : `AUTH_MODE`, `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, `OIDC_REDIRECT_URL`, plus `OIDC_SCOPES` et `OIDC_SESSION_TTL` optionnelles ; documentées dans `.env.example`, `docker-compose.yml`, `README.md` et `README.fr.md` (nouvelle section Authentification).
- Tests (`auth_test.go`) : flux complet contre un faux fournisseur en mémoire (RS256 et ES256), refus d'un nonce, d'une audience, d'un issuer ou d'une expiration incorrects, callback forgé, cookie de session forgé, configuration incomplète.
Non testé : l'interface dans un navigateur et un vrai fournisseur (Keycloak/Authentik).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
AUTH_MODE=local keeps the HTTP Basic authentication (unchanged default);
AUTH_MODE=oidc logs in through an OpenID Connect provider with the
authorization code flow and PKCE, standard library only: discovery,
ID token signature (RS/PS/ES) and claims checks, signed session cookie
whose key is kept in DATA_DIR. The UI gets a log out button and reloads
into the login when the session ends.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
claudeBot
marked the pull request as ready for review 2026-10-03 10:41:32 +02:00
claudeBot
merged commit ab38a54d54 into main2026-10-03 10:41:37 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Requested by Cédric
Avant : l'interface ne se protégeait que par une authentification HTTP Basic locale (
AUTH_USER/AUTH_PASS), ou pas du tout.Après :
AUTH_MODE=oidcdélègue la connexion à un fournisseur OpenID Connect (Keycloak, Authentik, Authelia…). Ouvrir l'interface renvoie vers la page de connexion du fournisseur puis revient sur la page demandée ; un bouton de déconnexion apparaît en haut à droite.AUTH_MODE=local(défaut) garde exactement le comportement actuel.Comment
auth.go(nouveau) : Basic Auth déplacée depuismain.gosans changement ; client OIDC en Go standard, sans dépendance : découverte.well-known, flux authorization code + PKCE S256,stateetnoncedans un cookie signé par connexion, échange du code (client_secret_basic, ou client_secret_post si le fournisseur n'accepte que lui), vérification de l'ID token (signature RS/PS/ES via JWKS avec rechargement à la rotation des clés,iss,aud,azp,exp,iat,nonce)./data/session.key(survit aux redémarrages), duréeOIDC_SESSION_TTL(12h)./api/*répond 401{"code":"auth"}que l'UI transforme en rechargement (donc en reconnexion)./healthzreste ouvert.AUTH_MODE,OIDC_ISSUER,OIDC_CLIENT_ID,OIDC_CLIENT_SECRET,OIDC_REDIRECT_URL, plusOIDC_SCOPESetOIDC_SESSION_TTLoptionnelles ; documentées dans.env.example,docker-compose.yml,README.mdetREADME.fr.md(nouvelle section Authentification).auth_test.go) : flux complet contre un faux fournisseur en mémoire (RS256 et ES256), refus d'un nonce, d'une audience, d'un issuer ou d'une expiration incorrects, callback forgé, cookie de session forgé, configuration incomplète.Non testé : l'interface dans un navigateur et un vrai fournisseur (Keycloak/Authentik).
🤖 Generated with Claude Code