From 6bec565b7afbd2add21cd61f116ca555c0524c63 Mon Sep 17 00:00:00 2001 From: cclohmar Date: Mon, 15 Jun 2026 08:12:32 +0000 Subject: [PATCH] feat(auth): force re-login after logout via prompt=login --- src/core/auth/oidc.go | 25 +++++++++++++++++++++++++ src/main.go | 20 +++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/core/auth/oidc.go b/src/core/auth/oidc.go index 048d9ea..139e9f9 100644 --- a/src/core/auth/oidc.go +++ b/src/core/auth/oidc.go @@ -228,9 +228,34 @@ func (h *OIDCHandler) AuthGateMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, ok := GetUserID(r) if !ok { + // Check if force-login is requested (after logout) + if _, ferr := r.Cookie("force_login"); ferr == nil { + http.SetCookie(w, &http.Cookie{Name: "force_login", Value: "", Path: "/", Domain: h.config.Domain, MaxAge: -1, HttpOnly: true}) + h.LoginRedirectWithPrompt(w, r, "login") + return + } h.LoginRedirect(w, r) return } next.ServeHTTP(w, r) }) } + +// LoginRedirectWithPrompt redirects with a specific prompt value. +func (h *OIDCHandler) LoginRedirectWithPrompt(w http.ResponseWriter, r *http.Request, prompt string) { + state := generateToken(16) + nonce := generateToken(16) + verifier := generateToken(32) + challenge := pkceChallenge(verifier) + + http.SetCookie(w, &http.Cookie{Name: "oidc_state", Value: state, Path: "/", Domain: h.config.Domain, MaxAge: 300, HttpOnly: true, SameSite: http.SameSiteLaxMode}) + http.SetCookie(w, &http.Cookie{Name: "oidc_verifier", Value: verifier, Path: "/", Domain: h.config.Domain, MaxAge: 300, HttpOnly: true, SameSite: http.SameSiteLaxMode}) + + authURL := fmt.Sprintf( + "%s/api/oidc/authorize?prompt=%s&response_type=code&client_id=%s&redirect_uri=%s&scope=openid+profile+email&state=%s&nonce=%s&code_challenge=%s&code_challenge_method=S256", + h.config.IssuerURL, prompt, + url.QueryEscape(h.config.ClientID), url.QueryEscape(h.config.RedirectURL), + state, nonce, challenge, + ) + http.Redirect(w, r, authURL, http.StatusFound) +} diff --git a/src/main.go b/src/main.go index 9a6b296..90abaa3 100644 --- a/src/main.go +++ b/src/main.go @@ -132,7 +132,25 @@ func main() { HttpOnly: true, SameSite: http.SameSiteLaxMode, }) - // Clear NextWks session, redirect to workspace (no session → Authelia login) + // Clear NextWks session and set force-login flag + http.SetCookie(w, &http.Cookie{ + Name: "nextwks_session", + Value: "", + Path: "/", + Domain: cfg.OIDC.Domain, + MaxAge: -1, + HttpOnly: true, + SameSite: http.SameSiteLaxMode, + }) + http.SetCookie(w, &http.Cookie{ + Name: "force_login", + Value: "1", + Path: "/", + Domain: cfg.OIDC.Domain, + MaxAge: 300, + HttpOnly: true, + SameSite: http.SameSiteLaxMode, + }) http.Redirect(w, r, "/", http.StatusFound) })