feat(auth): pass id_token_hint on Keycloak logout

Carries the raw ID token in the session cookie so logout can hand it back
to Keycloak as id_token_hint, letting it skip its own logout-confirmation
prompt -- otherwise a user could cancel out of it and land back in the app
with a Keycloak SSO session but no geniusrun profile (e.g. right after
deleting their account).
This commit is contained in:
2026-07-26 11:55:13 +02:00
parent d7202eb9bb
commit 8353cd148b
7 changed files with 191 additions and 26 deletions

View File

@@ -89,9 +89,16 @@ func (s *Server) handleSessionCallback(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, s.Session.FrontendURL+"/", http.StatusFound)
}
// handleSessionLogout clears geniusrun's own session cookie and redirects
// through Keycloak's end-session endpoint, passing the session's ID token
// as id_token_hint (see auth.Claims.IDToken) so Keycloak can skip its own
// logout-confirmation prompt -- otherwise a user could cancel out of it and
// land back on the app with a Keycloak SSO session but no geniusrun profile
// (already deleted, in the profile-deletion case this exists for).
func (s *Server) handleSessionLogout(w http.ResponseWriter, r *http.Request) {
claims, _ := auth.ClaimsFromContext(r.Context())
http.SetCookie(w, auth.ClearCookie(auth.SessionCookieName, s.Session.Secure))
http.Redirect(w, r, s.Auth.EndSessionURL(s.Session.FrontendURL+"/"), http.StatusFound)
http.Redirect(w, r, s.Auth.EndSessionURL(s.Session.FrontendURL+"/", claims.IDToken), http.StatusFound)
}
func (s *Server) handleSessionMe(w http.ResponseWriter, r *http.Request) {