mirror of
https://github.com/nais/wonderwall.git
synced 2026-05-10 18:37:00 +00:00
refactor(handler): use session cookie for frontchannel logout if available, clean up logout handlers
This commit is contained in:
@@ -5,8 +5,6 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/cookie"
|
||||
errorhandler "github.com/nais/wonderwall/pkg/handler/error"
|
||||
"github.com/nais/wonderwall/pkg/loginstatus"
|
||||
@@ -37,23 +35,26 @@ func Handler(src Source, w http.ResponseWriter, r *http.Request, opts Options) {
|
||||
return
|
||||
}
|
||||
|
||||
idToken := ""
|
||||
var idToken string
|
||||
|
||||
sessionData, err := src.GetSessions().Get(r)
|
||||
if err == nil && sessionData != nil {
|
||||
idToken = sessionData.IDToken
|
||||
sessions := src.GetSessions()
|
||||
|
||||
err = src.GetSessions().DestroyForID(r, sessionData.ExternalSessionID)
|
||||
if err != nil && !errors.Is(err, session.ErrKeyNotFound) {
|
||||
src.GetErrorHandler().InternalError(w, r, fmt.Errorf("logout: destroying session: %w", err))
|
||||
return
|
||||
key, err := sessions.GetKey(r)
|
||||
if err == nil {
|
||||
sessionData, err := sessions.GetForKey(r, key)
|
||||
if err == nil && sessionData != nil {
|
||||
idToken = sessionData.IDToken
|
||||
|
||||
err = sessions.Destroy(r, key)
|
||||
if err != nil && !errors.Is(err, session.ErrKeyNotFound) {
|
||||
src.GetErrorHandler().InternalError(w, r, fmt.Errorf("logout: destroying session: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
logger.WithField("jti", sessionData.IDTokenJwtID).
|
||||
Info("logout: successful local logout")
|
||||
metrics.ObserveLogout(metrics.LogoutOperationLocal)
|
||||
}
|
||||
|
||||
fields := log.Fields{
|
||||
"jti": sessionData.IDTokenJwtID,
|
||||
}
|
||||
logger.WithFields(fields).Info("logout: successful local logout")
|
||||
metrics.ObserveLogout(metrics.LogoutOperationLocal)
|
||||
}
|
||||
|
||||
cookie.Clear(w, cookie.Session, src.GetCookieOptsPathAware(r))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package logoutfrontchannel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/cookie"
|
||||
@@ -29,22 +30,23 @@ func Handler(src Source, w http.ResponseWriter, r *http.Request) {
|
||||
src.GetLoginstatus().ClearCookie(w, src.GetCookieOptions())
|
||||
}
|
||||
|
||||
logoutFrontchannel := src.GetClient().LogoutFrontchannel(r)
|
||||
if logoutFrontchannel.MissingSidParameter() {
|
||||
logger.Debug("front-channel logout: sid parameter not set in request; ignoring")
|
||||
sessions := src.GetSessions()
|
||||
client := src.GetClient()
|
||||
key, err := getSessionKey(r, sessions, client)
|
||||
if err != nil {
|
||||
logger.Debugf("front-channel logout: getting session key: %+v; ignoring", err)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
return
|
||||
}
|
||||
|
||||
sid := logoutFrontchannel.Sid()
|
||||
sessionData, err := src.GetSessions().GetForID(r, sid)
|
||||
sessionData, err := sessions.GetForKey(r, key)
|
||||
if err != nil {
|
||||
logger.Debugf("front-channel logout: could not get session (user might already be logged out): %+v", err)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
return
|
||||
}
|
||||
|
||||
err = src.GetSessions().DestroyForID(r, sid)
|
||||
err = sessions.Destroy(r, key)
|
||||
if err != nil {
|
||||
logger.Warnf("front-channel logout: destroying session: %+v", err)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
@@ -57,3 +59,18 @@ func Handler(src Source, w http.ResponseWriter, r *http.Request) {
|
||||
metrics.ObserveLogout(metrics.LogoutOperationFrontChannel)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func getSessionKey(r *http.Request, sessions *session.Handler, client *openidclient.Client) (string, error) {
|
||||
logoutFrontchannel := client.LogoutFrontchannel(r)
|
||||
|
||||
if logoutFrontchannel.MissingSidParameter() {
|
||||
key, err := sessions.GetKey(r)
|
||||
if err != nil {
|
||||
return key, nil
|
||||
}
|
||||
return "", fmt.Errorf("neither sid parameter nor session key found in request: %w", err)
|
||||
}
|
||||
|
||||
sid := logoutFrontchannel.Sid()
|
||||
return sessions.Key(sid), nil
|
||||
}
|
||||
|
||||
@@ -91,13 +91,8 @@ func (h *Handler) Create(r *http.Request, tokens *openid.Tokens, sessionLifetime
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// DestroyForID destroys a session for a given session ID. Note that a session ID is not equal to a session Key.
|
||||
func (h *Handler) DestroyForID(r *http.Request, id string) error {
|
||||
key := h.Key(id)
|
||||
return h.destroyForKey(r, key)
|
||||
}
|
||||
|
||||
func (h *Handler) destroyForKey(r *http.Request, key string) error {
|
||||
// Destroy destroys a session for a given session Key.
|
||||
func (h *Handler) Destroy(r *http.Request, key string) error {
|
||||
retryable := func(ctx context.Context) error {
|
||||
err := h.store.Delete(r.Context(), key)
|
||||
if err == nil {
|
||||
@@ -150,12 +145,6 @@ func (h *Handler) GetAccessToken(r *http.Request) (string, error) {
|
||||
return sessionData.AccessToken, nil
|
||||
}
|
||||
|
||||
// GetForID returns the session data for a given session ID.
|
||||
func (h *Handler) GetForID(r *http.Request, id string) (*Data, error) {
|
||||
key := h.Key(id)
|
||||
return h.GetForKey(r, key)
|
||||
}
|
||||
|
||||
// GetForKey returns the session data for a given session Key.
|
||||
func (h *Handler) GetForKey(r *http.Request, key string) (*Data, error) {
|
||||
var encryptedSessionData *EncryptedData
|
||||
|
||||
Reference in New Issue
Block a user