From a6fa4d8789e6044768330210d3f69e4a5f28f99a Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Wed, 6 Nov 2024 14:23:36 +0000 Subject: [PATCH] Downgrade gorilla sessions preventing the publishing by traefik hub temporarily. --- .traefik.yml | 1 + README.md | 1 + go.mod | 2 +- go.sum | 4 +- helpers.go | 166 +++++++++--------- main.go | 47 +++-- main_test.go | 40 ++--- settings.go | 1 + vendor/github.com/gorilla/sessions/LICENSE | 2 +- vendor/github.com/gorilla/sessions/README.md | 6 +- vendor/github.com/gorilla/sessions/cookie.go | 21 +-- .../gorilla/sessions/cookie_go111.go | 21 +++ vendor/github.com/gorilla/sessions/options.go | 15 +- .../gorilla/sessions/options_go111.go | 23 +++ vendor/modules.txt | 4 +- 15 files changed, 205 insertions(+), 149 deletions(-) create mode 100644 vendor/github.com/gorilla/sessions/cookie_go111.go create mode 100644 vendor/github.com/gorilla/sessions/options_go111.go diff --git a/.traefik.yml b/.traefik.yml index 478bdb7..0c33df0 100644 --- a/.traefik.yml +++ b/.traefik.yml @@ -13,6 +13,7 @@ testData: clientSecret: secret callbackURL: /oauth2/callback logoutURL: /oauth2/logout + postLogoutRedirectURI: /oidc/different-logout # If not provided it will redirect to the "/" URL scopes: # If not provided, default scopes will be used (openid, email, profile) - openid - email diff --git a/README.md b/README.md index a38ffe9..e6ee682 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ spec: sessionEncryptionKey: vvv callbackURL: /cool-oidc/callback logoutURL: /cool-oidc/logout + postLogoutRedirectURI: /my-website/you-have-logged-out # Optional post logout URL redirection scopes: - openid - email diff --git a/go.mod b/go.mod index 018a20d..0e2b4d9 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.23.1 require ( github.com/google/uuid v1.6.0 - github.com/gorilla/sessions v1.4.0 + github.com/gorilla/sessions v1.3.0 golang.org/x/time v0.7.0 ) diff --git a/go.sum b/go.sum index 2f64c57..2f28337 100644 --- a/go.sum +++ b/go.sum @@ -4,7 +4,7 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= -github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= -github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= +github.com/gorilla/sessions v1.3.0 h1:XYlkq7KcpOB2ZhHBPv5WpjMIxrQosiZanfoy1HLZFzg= +github.com/gorilla/sessions v1.3.0/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= diff --git a/helpers.go b/helpers.go index 8460f8e..216a593 100644 --- a/helpers.go +++ b/helpers.go @@ -27,14 +27,6 @@ func generateNonce() (string, error) { return base64.URLEncoding.EncodeToString(nonceBytes), nil } -// buildFullURL constructs a full URL from scheme, host, and path -func buildFullURL(scheme, host, path string) string { - if scheme == "" { - scheme = "http" - } - return fmt.Sprintf("%s://%s%s", scheme, host, path) -} - // exchangeTokens exchanges a code or refresh token for tokens func (t *TraefikOidc) exchangeTokens(ctx context.Context, grantType, codeOrToken, redirectURL string) (*TokenResponse, error) { data := url.Values{ @@ -97,78 +89,8 @@ func (t *TraefikOidc) getNewTokenWithRefreshToken(refreshToken string) (*TokenRe return tokenResponse, nil } -// handleLogout handles the logout process -func (t *TraefikOidc) handleLogout(w http.ResponseWriter, r *http.Request) { - session, err := t.store.Get(r, cookieName) - if err != nil { - handleError(w, fmt.Sprintf("Error getting session: %v", err), http.StatusInternalServerError, t.logger) - return - } - - // Get tokens from session - idToken, _ := session.Values["id_token"].(string) - refreshToken, _ := session.Values["refresh_token"].(string) - accessToken, _ := session.Values["access_token"].(string) - - // Revoke tokens if they exist - if refreshToken != "" { - t.RevokeTokenWithProvider(refreshToken, "refresh_token") - t.RevokeToken(refreshToken) - } - if accessToken != "" { - t.RevokeTokenWithProvider(accessToken, "access_token") - t.RevokeToken(accessToken) - } - - // Clear session - session.Options.MaxAge = -1 - session.Values = make(map[interface{}]interface{}) - if err := session.Save(r, w); err != nil { - handleError(w, fmt.Sprintf("Error saving session: %v", err), http.StatusInternalServerError, t.logger) - return - } - - // Determine redirect URL - host := r.Header.Get("X-Forwarded-Host") - if host == "" { - host = r.Host - } - scheme := "http" - if r.Header.Get("X-Forwarded-Proto") == "https" || t.forceHTTPS { - scheme = "https" - } - baseURL := fmt.Sprintf("%s://%s/", scheme, host) - - if t.endSessionURL != "" && idToken != "" { - logoutURL, err := BuildLogoutURL(t.endSessionURL, idToken, baseURL) - if err != nil { - handleError(w, fmt.Sprintf("Invalid end session URL: %v", err), http.StatusInternalServerError, t.logger) - return - } - http.Redirect(w, r, logoutURL, http.StatusFound) - return - } - - http.Redirect(w, r, baseURL, http.StatusFound) -} - -// BuildLogoutURL constructs the logout URL with proper encoding -func BuildLogoutURL(endSessionURL, idToken, postLogoutRedirectURI string) (string, error) { - u, err := url.Parse(endSessionURL) - if err != nil { - return "", fmt.Errorf("invalid end session URL: %v", err) - } - - q := u.Query() - q.Set("id_token_hint", idToken) - q.Set("post_logout_redirect_uri", postLogoutRedirectURI) - u.RawQuery = q.Encode() - - return u.String(), nil -} - // handleExpiredToken handles the case when a token has expired -func (t *TraefikOidc) handleExpiredToken(rw http.ResponseWriter, req *http.Request, session *sessions.Session) { +func (t *TraefikOidc) handleExpiredToken(rw http.ResponseWriter, req *http.Request, session *sessions.Session, redirectURL string) { // Clear the existing session session.Options.MaxAge = -1 for k := range session.Values { @@ -189,11 +111,11 @@ func (t *TraefikOidc) handleExpiredToken(rw http.ResponseWriter, req *http.Reque } // Initiate a new authentication flow - t.initiateAuthenticationFunc(rw, req, session, t.redirectURL) + t.initiateAuthenticationFunc(rw, req, session, redirectURL) } // handleCallback handles the callback from the OIDC provider -func (t *TraefikOidc) handleCallback(rw http.ResponseWriter, req *http.Request) { +func (t *TraefikOidc) handleCallback(rw http.ResponseWriter, req *http.Request, redirectURL string) { session, err := t.store.Get(req, cookieName) if err != nil { t.logger.Errorf("Session error: %v", err) @@ -238,7 +160,7 @@ func (t *TraefikOidc) handleCallback(rw http.ResponseWriter, req *http.Request) return } - tokenResponse, err := t.exchangeCodeForTokenFunc(code) + tokenResponse, err := t.exchangeCodeForTokenFunc(code, redirectURL) if err != nil { t.logger.Errorf("Failed to exchange code for token: %v", err) http.Error(rw, "Authentication failed", http.StatusInternalServerError) @@ -424,9 +346,9 @@ func (tc *TokenCache) Cleanup() { } // exchangeCodeForToken exchanges the authorization code for tokens -func (t *TraefikOidc) exchangeCodeForToken(code string) (*TokenResponse, error) { +func (t *TraefikOidc) exchangeCodeForToken(code string, redirectURL string) (*TokenResponse, error) { ctx := context.Background() - tokenResponse, err := t.exchangeTokens(ctx, "authorization_code", code, t.redirectURL) + tokenResponse, err := t.exchangeTokens(ctx, "authorization_code", code, redirectURL) if err != nil { return nil, fmt.Errorf("failed to exchange code for token: %w", err) } @@ -441,3 +363,79 @@ func createStringMap(keys []string) map[string]struct{} { } return result } + +// handleLogout handles the logout request +func (t *TraefikOidc) handleLogout(rw http.ResponseWriter, req *http.Request) { + session, err := t.store.Get(req, cookieName) + if err != nil { + t.logger.Errorf("Error getting session: %v", err) + http.Error(rw, "Session error", http.StatusInternalServerError) + return + } + + // Get the id_token before clearing the session + idToken, _ := session.Values["id_token"].(string) + + // Clear and expire the session + session.Values = make(map[interface{}]interface{}) + session.Options.MaxAge = -1 + if err := session.Save(req, rw); err != nil { + t.logger.Errorf("Error saving session: %v", err) + http.Error(rw, "Session error", http.StatusInternalServerError) + return + } + + // Get the base URL for redirects + host := t.determineHost(req) + scheme := t.determineScheme(req) + baseURL := fmt.Sprintf("%s://%s", scheme, host) + + // Determine post logout redirect URI + var postLogoutRedirectURI string + if t.postLogoutRedirectURI != "" { + // Use explicitly configured postLogoutRedirectURI + if strings.HasPrefix(t.postLogoutRedirectURI, "http://") || strings.HasPrefix(t.postLogoutRedirectURI, "https://") { + postLogoutRedirectURI = t.postLogoutRedirectURI + } else { + postLogoutRedirectURI = fmt.Sprintf("%s%s", baseURL, t.postLogoutRedirectURI) + } + } else { + postLogoutRedirectURI = fmt.Sprintf("%s%s", baseURL, "/") + } + + t.logger.Debugf("Using post logout redirect URI: %s", postLogoutRedirectURI) + + // If we have an end session endpoint and an ID token, use OIDC end session + if t.endSessionURL != "" && idToken != "" { + logoutURL, err := BuildLogoutURL(t.endSessionURL, idToken, postLogoutRedirectURI) + if err != nil { + handleError(rw, fmt.Sprintf("Failed to build logout URL: %v", err), http.StatusInternalServerError, t.logger) + return + } + t.logger.Debugf("Redirecting to end session URL: %s", logoutURL) + http.Redirect(rw, req, logoutURL, http.StatusFound) + return + } + + // If no end session endpoint or no ID token, just redirect to the post logout URI + t.logger.Debugf("Redirecting to post logout URI: %s", postLogoutRedirectURI) + http.Redirect(rw, req, postLogoutRedirectURI, http.StatusFound) +} + +// BuildLogoutURL constructs the OIDC end session URL +func BuildLogoutURL(endSessionURL, idToken, postLogoutRedirectURI string) (string, error) { + u, err := url.Parse(endSessionURL) + if err != nil { + return "", fmt.Errorf("failed to parse end session URL: %w", err) + } + + q := u.Query() + q.Set("id_token_hint", idToken) + if postLogoutRedirectURI != "" { + // Ensure postLogoutRedirectURI is properly URL encoded + q.Set("post_logout_redirect_uri", postLogoutRedirectURI) + } + u.RawQuery = q.Encode() + + return u.String(), nil +} diff --git a/main.go b/main.go index a581dbf..7be689a 100644 --- a/main.go +++ b/main.go @@ -53,18 +53,18 @@ type TraefikOidc struct { tokenCache *TokenCache httpClient *http.Client logger *Logger - redirectURL string tokenVerifier TokenVerifier jwtVerifier JWTVerifier excludedURLs map[string]struct{} allowedUserDomains map[string]struct{} allowedRolesAndGroups map[string]struct{} initiateAuthenticationFunc func(rw http.ResponseWriter, req *http.Request, session *sessions.Session, redirectURL string) - exchangeCodeForTokenFunc func(code string) (*TokenResponse, error) + exchangeCodeForTokenFunc func(code string, redirectURL string) (*TokenResponse, error) extractClaimsFunc func(tokenString string) (map[string]interface{}, error) initComplete chan struct{} endSessionURL string baseURL string + postLogoutRedirectURI string } // ProviderMetadata holds OIDC provider metadata @@ -227,6 +227,12 @@ func New(ctx context.Context, next http.Handler, config *Config, name string) (h } return config.LogoutURL }(), + postLogoutRedirectURI: func() string { + if config.PostLogoutRedirectURI == "" { + return "/" + } + return config.PostLogoutRedirectURI + }(), tokenBlacklist: NewTokenBlacklist(), jwkCache: &JWKCache{}, clientID: config.ClientID, @@ -375,10 +381,12 @@ func (t *TraefikOidc) ServeHTTP(rw http.ResponseWriter, req *http.Request) { defaultSessionOptions.Secure = t.scheme == "https" host := t.determineHost(req) + redirectURL := buildFullURL(t.scheme, host, t.redirURLPath) + // Build the redirect URL if not already set - if t.redirectURL == "" { - t.redirectURL = buildFullURL(t.scheme, host, t.redirURLPath) - t.logger.Debugf("Redirect URL updated to: %s", t.redirectURL) + if redirectURL == "" { + redirectURL = buildFullURL(t.scheme, host, t.redirURLPath) + t.logger.Debugf("Redirect URL updated to: %s", redirectURL) } // Get the session @@ -399,7 +407,7 @@ func (t *TraefikOidc) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // Handle callback URL if req.URL.Path == t.redirURLPath { - t.handleCallback(rw, req) + t.handleCallback(rw, req, redirectURL) return } @@ -407,19 +415,19 @@ func (t *TraefikOidc) ServeHTTP(rw http.ResponseWriter, req *http.Request) { authenticated, needsRefresh, expired := t.isUserAuthenticated(session) if expired { - t.handleExpiredToken(rw, req, session) + t.handleExpiredToken(rw, req, session, redirectURL) return } if !authenticated { - t.defaultInitiateAuthentication(rw, req, session, t.redirectURL) + t.defaultInitiateAuthentication(rw, req, session, redirectURL) return } if needsRefresh { refreshed := t.refreshToken(rw, req, session) if !refreshed { - t.handleExpiredToken(rw, req, session) + t.handleExpiredToken(rw, req, session, redirectURL) return } } @@ -428,21 +436,21 @@ func (t *TraefikOidc) ServeHTTP(rw http.ResponseWriter, req *http.Request) { idToken, ok := session.Values["id_token"].(string) if !ok || idToken == "" { t.logger.Errorf("No id_token found in session") - t.defaultInitiateAuthentication(rw, req, session, t.redirectURL) + t.defaultInitiateAuthentication(rw, req, session, redirectURL) return } claims, err := extractClaims(idToken) if err != nil { t.logger.Errorf("Failed to extract claims: %v", err) - t.defaultInitiateAuthentication(rw, req, session, t.redirectURL) + t.defaultInitiateAuthentication(rw, req, session, redirectURL) return } email, _ := claims["email"].(string) if email == "" { t.logger.Debugf("No email found in token claims") - t.defaultInitiateAuthentication(rw, req, session, t.redirectURL) + t.defaultInitiateAuthentication(rw, req, session, redirectURL) return } @@ -767,3 +775,18 @@ func (t *TraefikOidc) extractGroupsAndRoles(idToken string) ([]string, []string, return groups, roles, nil } + +// buildFullURL constructs a full URL from scheme, host and path +func buildFullURL(scheme, host, path string) string { + // If the path is already a full URL, return it as-is + if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") { + return path + } + + // Ensure the path starts with a forward slash + if !strings.HasPrefix(path, "/") { + path = "/" + path + } + + return fmt.Sprintf("%s://%s%s", scheme, host, path) +} diff --git a/main_test.go b/main_test.go index eeef592..530d28f 100644 --- a/main_test.go +++ b/main_test.go @@ -104,7 +104,7 @@ func (ts *TestSuite) Setup() { } // Helper functions used by TraefikOidc -func (ts *TestSuite) exchangeCodeForTokenFunc(code string) (*TokenResponse, error) { +func (ts *TestSuite) exchangeCodeForTokenFunc(code string, redirectURL string) (*TokenResponse, error) { return &TokenResponse{ IDToken: ts.token, RefreshToken: "test-refresh-token", @@ -452,10 +452,12 @@ func TestHandleCallback(t *testing.T) { ts := &TestSuite{t: t} ts.Setup() + redirectURL := "http://example.com/" + tests := []struct { name string queryParams string - exchangeCodeForToken func(code string) (*TokenResponse, error) + exchangeCodeForToken func(code string, redirectURL string) (*TokenResponse, error) extractClaimsFunc func(tokenString string) (map[string]interface{}, error) sessionSetupFunc func(session *sessions.Session) expectedStatus int @@ -463,7 +465,7 @@ func TestHandleCallback(t *testing.T) { { name: "Success", queryParams: "?code=test-code&state=test-csrf-token", - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { return &TokenResponse{ IDToken: ts.token, RefreshToken: "test-refresh-token", @@ -493,7 +495,7 @@ func TestHandleCallback(t *testing.T) { { name: "Exchange Code Error", queryParams: "?code=test-code&state=test-csrf-token", - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { return nil, fmt.Errorf("exchange code error") }, sessionSetupFunc: func(session *sessions.Session) { @@ -505,7 +507,7 @@ func TestHandleCallback(t *testing.T) { { name: "Missing ID Token", queryParams: "?code=test-code&state=test-csrf-token", - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { return &TokenResponse{}, nil }, sessionSetupFunc: func(session *sessions.Session) { @@ -517,7 +519,7 @@ func TestHandleCallback(t *testing.T) { { name: "Disallowed Email", queryParams: "?code=test-code&state=test-csrf-token", - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { return &TokenResponse{ IDToken: ts.token, RefreshToken: "test-refresh-token", @@ -538,7 +540,7 @@ func TestHandleCallback(t *testing.T) { { name: "Invalid State Parameter", queryParams: "?code=test-code&state=invalid-csrf-token", - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { return &TokenResponse{ IDToken: ts.token, RefreshToken: "test-refresh-token", @@ -559,7 +561,7 @@ func TestHandleCallback(t *testing.T) { { name: "Nonce Mismatch", queryParams: "?code=test-code&state=test-csrf-token", - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { return &TokenResponse{ IDToken: ts.token, RefreshToken: "test-refresh-token", @@ -580,7 +582,7 @@ func TestHandleCallback(t *testing.T) { { name: "Missing Nonce in Claims", queryParams: "?code=test-code&state=test-csrf-token", - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { return &TokenResponse{ IDToken: ts.token, RefreshToken: "test-refresh-token", @@ -633,7 +635,7 @@ func TestHandleCallback(t *testing.T) { rr = httptest.NewRecorder() // Call handleCallback - tOidc.handleCallback(rr, req) + tOidc.handleCallback(rr, req, redirectURL) // Check response if rr.Code != tc.expectedStatus { @@ -688,7 +690,7 @@ func TestOIDCHandler(t *testing.T) { tests := []struct { name string queryParams string - exchangeCodeForToken func(code string) (*TokenResponse, error) + exchangeCodeForToken func(code string, redirectURL string) (*TokenResponse, error) extractClaimsFunc func(tokenString string) (map[string]interface{}, error) sessionSetupFunc func(session *sessions.Session) expectedStatus int @@ -704,7 +706,7 @@ func TestOIDCHandler(t *testing.T) { session.Values["csrf"] = "test-csrf-token" session.Values["nonce"] = "test-nonce" }, - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { // Simulate token exchange return &TokenResponse{ IDToken: ts.token, @@ -728,7 +730,7 @@ func TestOIDCHandler(t *testing.T) { session.Values["csrf"] = "test-csrf-token" session.Values["nonce"] = "test-nonce" }, - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { // Simulate token exchange return &TokenResponse{ IDToken: ts.token, @@ -751,7 +753,7 @@ func TestOIDCHandler(t *testing.T) { session.Values["csrf"] = "test-csrf-token" session.Values["nonce"] = "test-nonce" }, - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { // Simulate token exchange return &TokenResponse{ IDToken: ts.token, @@ -775,7 +777,7 @@ func TestOIDCHandler(t *testing.T) { session.Values["csrf"] = "test-csrf-token" session.Values["nonce"] = "test-nonce" }, - exchangeCodeForToken: func(code string) (*TokenResponse, error) { + exchangeCodeForToken: func(code string, redirectURL string) (*TokenResponse, error) { // Simulate token exchange return &TokenResponse{ IDToken: ts.token, @@ -863,9 +865,8 @@ func TestHandleLogout(t *testing.T) { }, endSessionURL: "https://provider/end-session", expectedStatus: http.StatusFound, - // Fix: The entire URL should be URL-encoded - expectedURL: "https://provider/end-session?id_token_hint=test.id.token&post_logout_redirect_uri=http%3A%2F%2Fexample.com%2F", - host: "test-host", + expectedURL: "https://provider/end-session?id_token_hint=test.id.token&post_logout_redirect_uri=http%3A%2F%2Fexample.com%2F", + host: "test-host", }, { name: "Successful logout without end session endpoint", @@ -1184,7 +1185,6 @@ func TestHandleExpiredToken(t *testing.T) { tOidc := &TraefikOidc{ store: sessions.NewCookieStore([]byte("test-secret-key")), logger: NewLogger("info"), - redirectURL: "http://example.com/callback", tokenVerifier: ts.tOidc.tokenVerifier, jwtVerifier: ts.tOidc.jwtVerifier, initComplete: make(chan struct{}), @@ -1205,7 +1205,7 @@ func TestHandleExpiredToken(t *testing.T) { tc.setupSession(session) // Handle expired token - tOidc.handleExpiredToken(rr, req, session) + tOidc.handleExpiredToken(rr, req, session, tc.expectedPath) // Verify session is cleaned if len(session.Values) != 3 { // Should only have csrf, incoming_path, and nonce diff --git a/settings.go b/settings.go index 053170b..c1f11c1 100644 --- a/settings.go +++ b/settings.go @@ -31,6 +31,7 @@ type Config struct { AllowedUserDomains []string `json:"allowedUserDomains"` AllowedRolesAndGroups []string `json:"allowedRolesAndGroups"` OIDCEndSessionURL string `json:"oidcEndSessionURL"` + PostLogoutRedirectURI string `json:"postLogoutRedirectURI"` HTTPClient *http.Client } diff --git a/vendor/github.com/gorilla/sessions/LICENSE b/vendor/github.com/gorilla/sessions/LICENSE index 7fa9009..bb9d80b 100644 --- a/vendor/github.com/gorilla/sessions/LICENSE +++ b/vendor/github.com/gorilla/sessions/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2024 The Gorilla Authors. All rights reserved. +Copyright (c) 2023 The Gorilla Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/gorilla/sessions/README.md b/vendor/github.com/gorilla/sessions/README.md index d2cbea6..3aef6a4 100644 --- a/vendor/github.com/gorilla/sessions/README.md +++ b/vendor/github.com/gorilla/sessions/README.md @@ -1,7 +1,4 @@ -# Gorilla Sessions - -> [!IMPORTANT] -> The latest version of this repository requires go 1.23 because of the new partitioned attribute. The last version that is compatible with older versions of go is v1.3.0. +# sessions ![testing](https://github.com/gorilla/sessions/actions/workflows/test.yml/badge.svg) [![codecov](https://codecov.io/github/gorilla/sessions/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/sessions) @@ -77,7 +74,6 @@ Other implementations of the `sessions.Store` interface: - [github.com/dsoprea/go-appengine-sessioncascade](https://github.com/dsoprea/go-appengine-sessioncascade) - Memcache/Datastore/Context in AppEngine - [github.com/kidstuff/mongostore](https://github.com/kidstuff/mongostore) - MongoDB - [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore) - MySQL -- [github.com/danielepintore/gorilla-sessions-mysql](https://github.com/danielepintore/gorilla-sessions-mysql) - MySQL - [github.com/EnumApps/clustersqlstore](https://github.com/EnumApps/clustersqlstore) - MySQL Cluster - [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL - [github.com/boj/redistore](https://github.com/boj/redistore) - Redis diff --git a/vendor/github.com/gorilla/sessions/cookie.go b/vendor/github.com/gorilla/sessions/cookie.go index fd6f48c..6612662 100644 --- a/vendor/github.com/gorilla/sessions/cookie.go +++ b/vendor/github.com/gorilla/sessions/cookie.go @@ -1,6 +1,5 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +//go:build !go1.11 +// +build !go1.11 package sessions @@ -9,15 +8,13 @@ import "net/http" // newCookieFromOptions returns an http.Cookie with the options set. func newCookieFromOptions(name, value string, options *Options) *http.Cookie { return &http.Cookie{ - Name: name, - Value: value, - Path: options.Path, - Domain: options.Domain, - MaxAge: options.MaxAge, - Secure: options.Secure, - HttpOnly: options.HttpOnly, - Partitioned: options.Partitioned, - SameSite: options.SameSite, + Name: name, + Value: value, + Path: options.Path, + Domain: options.Domain, + MaxAge: options.MaxAge, + Secure: options.Secure, + HttpOnly: options.HttpOnly, } } diff --git a/vendor/github.com/gorilla/sessions/cookie_go111.go b/vendor/github.com/gorilla/sessions/cookie_go111.go new file mode 100644 index 0000000..9b58828 --- /dev/null +++ b/vendor/github.com/gorilla/sessions/cookie_go111.go @@ -0,0 +1,21 @@ +//go:build go1.11 +// +build go1.11 + +package sessions + +import "net/http" + +// newCookieFromOptions returns an http.Cookie with the options set. +func newCookieFromOptions(name, value string, options *Options) *http.Cookie { + return &http.Cookie{ + Name: name, + Value: value, + Path: options.Path, + Domain: options.Domain, + MaxAge: options.MaxAge, + Secure: options.Secure, + HttpOnly: options.HttpOnly, + SameSite: options.SameSite, + } + +} diff --git a/vendor/github.com/gorilla/sessions/options.go b/vendor/github.com/gorilla/sessions/options.go index 6ed7934..d33d076 100644 --- a/vendor/github.com/gorilla/sessions/options.go +++ b/vendor/github.com/gorilla/sessions/options.go @@ -1,11 +1,8 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +//go:build !go1.11 +// +build !go1.11 package sessions -import "net/http" - // Options stores configuration for a session or session store. // // Fields are a subset of http.Cookie fields. @@ -16,9 +13,7 @@ type Options struct { // deleted after the browser session ends. // MaxAge<0 means delete cookie immediately. // MaxAge>0 means Max-Age attribute present and given in seconds. - MaxAge int - Secure bool - HttpOnly bool - Partitioned bool - SameSite http.SameSite + MaxAge int + Secure bool + HttpOnly bool } diff --git a/vendor/github.com/gorilla/sessions/options_go111.go b/vendor/github.com/gorilla/sessions/options_go111.go new file mode 100644 index 0000000..af9cdf0 --- /dev/null +++ b/vendor/github.com/gorilla/sessions/options_go111.go @@ -0,0 +1,23 @@ +//go:build go1.11 +// +build go1.11 + +package sessions + +import "net/http" + +// Options stores configuration for a session or session store. +// +// Fields are a subset of http.Cookie fields. +type Options struct { + Path string + Domain string + // MaxAge=0 means no Max-Age attribute specified and the cookie will be + // deleted after the browser session ends. + // MaxAge<0 means delete cookie immediately. + // MaxAge>0 means Max-Age attribute present and given in seconds. + MaxAge int + Secure bool + HttpOnly bool + // Defaults to http.SameSiteDefaultMode + SameSite http.SameSite +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2e7e35e..ed56d4b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -4,8 +4,8 @@ github.com/google/uuid # github.com/gorilla/securecookie v1.1.2 ## explicit; go 1.20 github.com/gorilla/securecookie -# github.com/gorilla/sessions v1.4.0 -## explicit; go 1.23 +# github.com/gorilla/sessions v1.3.0 +## explicit; go 1.20 github.com/gorilla/sessions # golang.org/x/time v0.7.0 ## explicit; go 1.18