diff --git a/cmd/start.go b/cmd/start.go index a07be9e..7b87097 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -19,6 +19,7 @@ package cmd import ( "log" "net/http" + "net/url" "context" @@ -80,6 +81,37 @@ var startCmd = &cobra.Command{ // Register handlers httpRequestRouter.HandleFunc("/login", middleware.LoginHandler(authConfig)) httpRequestRouter.HandleFunc("/callback", middleware.CallbackHandler(authConfig)) + // Update the logout handler to include Keycloak integration + httpRequestRouter.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) { + // 1. Get session and immediately expire it + session, _ := authConfig.Store.Get(r, "auth-session") + session.Values["authenticated"] = false + session.Options.MaxAge = -1 // Immediate deletion + session.Save(r, w) + + // 2. Keycloak logout parameters + keycloakLogoutURL, err := url.Parse(viper.GetString("issuer-url") + "/protocol/openid-connect/logout") + if err != nil { + log.Printf("Error parsing logout URL: %v", err) + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } + + // 3. Build logout URL with post_logout_redirect_uri and id_token_hint + q := keycloakLogoutURL.Query() + q.Set("post_logout_redirect_uri", viper.GetString("redirect-url")) + q.Set("client_id", viper.GetString("client-id")) + + // Retrieve ID token from session if available + if idToken, ok := session.Values["id_token"].(string); ok { + q.Set("id_token_hint", idToken) + } + + keycloakLogoutURL.RawQuery = q.Encode() + + // 4. Redirect to Keycloak for global session termination + http.Redirect(w, r, keycloakLogoutURL.String(), http.StatusFound) + }) // Update middleware stack stack := middleware.CreateStack( diff --git a/site/components/dashboard.html b/site/components/dashboard.html new file mode 100644 index 0000000..f345eb4 --- /dev/null +++ b/site/components/dashboard.html @@ -0,0 +1,51 @@ + + +
+ + +Please log in to continue
+ +Are you sure you want to log out?
+ +