From 05e2509fac8f955869ccf8e1e9ef24e7042f9863 Mon Sep 17 00:00:00 2001 From: Trong Huu Nguyen Date: Fri, 7 Jan 2022 11:03:22 +0100 Subject: [PATCH] refactor: separate cookie operations to own package --- pkg/cookie/cookie.go | 91 ++++++++++++++++++++++ pkg/cookie/cookie_test.go | 97 ++++++++++++++++++++++++ pkg/cookie/options.go | 34 +++++++++ pkg/cookie/options_test.go | 63 +++++++++++++++ pkg/router/cookies.go | 93 +++-------------------- pkg/router/handler.go | 38 +++++----- pkg/router/handler_callback.go | 3 +- pkg/router/handler_frontchannellogout.go | 2 +- pkg/router/handler_login.go | 46 ++++++++++- pkg/router/handler_logout.go | 5 +- pkg/router/router_test.go | 18 +++-- pkg/router/session.go | 6 +- pkg/router/session_fallback.go | 22 +++--- 13 files changed, 389 insertions(+), 129 deletions(-) create mode 100644 pkg/cookie/cookie.go create mode 100644 pkg/cookie/cookie_test.go create mode 100644 pkg/cookie/options.go create mode 100644 pkg/cookie/options_test.go diff --git a/pkg/cookie/cookie.go b/pkg/cookie/cookie.go new file mode 100644 index 0000000..3a0be36 --- /dev/null +++ b/pkg/cookie/cookie.go @@ -0,0 +1,91 @@ +package cookie + +import ( + "encoding/base64" + "fmt" + "net/http" + "time" + + "github.com/nais/wonderwall/pkg/crypto" +) + +type Cookie struct { + *http.Cookie +} + +func (in Cookie) Encrypt(crypter crypto.Crypter) (*Cookie, error) { + plaintext := []byte(in.Cookie.Value) + ciphertext, err := crypter.Encrypt(plaintext) + if err != nil { + return nil, fmt.Errorf("unable to encrypt cookie '%s': %w", in.Cookie.Name, err) + } + + value := base64.StdEncoding.EncodeToString(ciphertext) + + encryptedCookie := in.Cookie + encryptedCookie.Value = value + + return &Cookie{encryptedCookie}, nil +} + +func (in Cookie) Decrypt(crypter crypto.Crypter) (string, error) { + ciphertext, err := base64.StdEncoding.DecodeString(in.Value) + if err != nil { + return "", fmt.Errorf("value for cookie '%s' is not base64 encoded: %w", in.Name, err) + } + + plaintext, err := crypter.Decrypt(ciphertext) + if err != nil { + return "", fmt.Errorf("unable to decrypt cookie '%s': %w", in.Name, err) + } + + return string(plaintext), err +} + +func Clear(w http.ResponseWriter, name string, opts Options) { + expires := time.Now().Add(-7 * 24 * time.Hour) + maxAge := -1 + + cookie := &http.Cookie{ + Expires: expires, + HttpOnly: true, + MaxAge: maxAge, + Name: name, + Path: "/", + SameSite: opts.SameSite, + Secure: opts.Secure, + } + + http.SetCookie(w, cookie) +} + +func Get(r *http.Request, key string) (*Cookie, error) { + cookie, err := r.Cookie(key) + if err != nil { + return nil, fmt.Errorf("no cookie named '%s': %w", key, err) + } + + return &Cookie{cookie}, nil +} + +func Make(name, value string, opts Options) *Cookie { + expires := time.Now().Add(opts.ExpiresIn) + maxAge := int(opts.ExpiresIn.Seconds()) + + cookie := &http.Cookie{ + Expires: expires, + HttpOnly: true, + MaxAge: maxAge, + Name: name, + Path: "/", + SameSite: opts.SameSite, + Secure: opts.Secure, + Value: value, + } + + return &Cookie{cookie} +} + +func Set(w http.ResponseWriter, cookie *Cookie) { + http.SetCookie(w, cookie.Cookie) +} diff --git a/pkg/cookie/cookie_test.go b/pkg/cookie/cookie_test.go new file mode 100644 index 0000000..99d2977 --- /dev/null +++ b/pkg/cookie/cookie_test.go @@ -0,0 +1,97 @@ +package cookie_test + +import ( + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/nais/wonderwall/pkg/cookie" + "github.com/nais/wonderwall/pkg/crypto" +) + +var ( + encryptionKey = `G8Roe6AcoBpdr5GhO3cs9iORl4XIC8eq` // 256 bits AES +) + +func TestMake(t *testing.T) { + expiresIn := 5 * time.Minute + opts := cookie.DefaultOptions().WithExpiresIn(expiresIn) + + name := "some-cookie" + value := "some-value" + + result := cookie.Make(name, value, opts) + + shouldExpireBefore := time.Now().Add(expiresIn) + assert.True(t, result.Expires.Before(shouldExpireBefore)) + assert.Equal(t, int(opts.ExpiresIn.Seconds()), result.MaxAge) + assert.True(t, result.HttpOnly) + assert.Equal(t, name, result.Name) + assert.Equal(t, value, result.Value) + assert.Equal(t, opts.SameSite, result.SameSite) + assert.Equal(t, opts.Secure, result.Secure) + assert.Equal(t, "/", result.Path) +} + +func TestClear(t *testing.T) { + opts := cookie.DefaultOptions() + name := "some-name" + + writer := httptest.NewRecorder() + cookie.Clear(writer, name, opts) + + cookies := writer.Result().Cookies() + + var result *http.Cookie + for _, c := range cookies { + if c.Name == name { + result = c + } + } + + shouldExpireBefore := time.Now().Add(-7 * 24 * time.Hour) + + assert.NotNil(t, result) + assert.True(t, result.Expires.Before(time.Now())) + assert.True(t, result.Expires.Before(shouldExpireBefore)) + assert.Equal(t, -1, result.MaxAge) + assert.True(t, result.HttpOnly) + assert.Equal(t, name, result.Name) + assert.Equal(t, "", result.Value) + assert.Equal(t, opts.SameSite, result.SameSite) + assert.Equal(t, opts.Secure, result.Secure) + assert.Equal(t, "/", result.Path) +} + +func TestCookie_Encrypt(t *testing.T) { + crypter := crypto.NewCrypter([]byte(encryptionKey)) + + opts := cookie.DefaultOptions().WithExpiresIn(1 * time.Minute) + name := "some-name" + value := "some-value" + + plaintextCookie := cookie.Make(name, value, opts) + encryptedCookie, err := plaintextCookie.Encrypt(crypter) + assert.NoError(t, err) + assert.NotEqual(t, value, encryptedCookie.Value) +} + +func TestCookie_Decrypt(t *testing.T) { + crypter := crypto.NewCrypter([]byte(encryptionKey)) + + opts := cookie.DefaultOptions().WithExpiresIn(1 * time.Minute) + name := "some-name" + value := "some-value" + + plaintextCookie := cookie.Make(name, value, opts) + encryptedCookie, err := plaintextCookie.Encrypt(crypter) + assert.NoError(t, err) + assert.NotEqual(t, value, encryptedCookie.Value) + + plaintext, err := encryptedCookie.Decrypt(crypter) + assert.NoError(t, err) + assert.Equal(t, value, plaintext) +} diff --git a/pkg/cookie/options.go b/pkg/cookie/options.go new file mode 100644 index 0000000..2de58c5 --- /dev/null +++ b/pkg/cookie/options.go @@ -0,0 +1,34 @@ +package cookie + +import ( + "net/http" + "time" +) + +type Options struct { + ExpiresIn time.Duration + SameSite http.SameSite + Secure bool +} + +func DefaultOptions() Options { + return Options{ + SameSite: http.SameSiteLaxMode, + Secure: true, + } +} + +func (o Options) WithSameSite(sameSite http.SameSite) Options { + o.SameSite = sameSite + return o +} + +func (o Options) WithExpiresIn(expiresIn time.Duration) Options { + o.ExpiresIn = expiresIn + return o +} + +func (o Options) WithSecure(secure bool) Options { + o.Secure = secure + return o +} diff --git a/pkg/cookie/options_test.go b/pkg/cookie/options_test.go new file mode 100644 index 0000000..73ae04a --- /dev/null +++ b/pkg/cookie/options_test.go @@ -0,0 +1,63 @@ +package cookie_test + +import ( + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/nais/wonderwall/pkg/cookie" +) + +func TestDefaultOptions(t *testing.T) { + opts := cookie.DefaultOptions() + + assert.Equal(t, http.SameSiteLaxMode, opts.SameSite) + assert.True(t, opts.Secure) + assert.Empty(t, opts.ExpiresIn) +} + +func TestOptions_WithExpiresIn(t *testing.T) { + expiresIn := 1 * time.Minute + opts := cookie.Options{}.WithExpiresIn(expiresIn) + + assert.Equal(t, 1*time.Minute, opts.ExpiresIn) + + opts = cookie.Options{ + ExpiresIn: 2 * time.Minute, + } + newOpts := opts.WithExpiresIn(expiresIn) + + assert.Equal(t, 2*time.Minute, opts.ExpiresIn, "original options should be unchanged") + assert.Equal(t, 1*time.Minute, newOpts.ExpiresIn, "copy of options should have new value") +} + +func TestOptions_WithSameSite(t *testing.T) { + sameSite := http.SameSiteDefaultMode + opts := cookie.Options{}.WithSameSite(sameSite) + + assert.Equal(t, http.SameSiteDefaultMode, opts.SameSite) + + opts = cookie.Options{ + SameSite: http.SameSiteLaxMode, + } + newOpts := opts.WithSameSite(sameSite) + + assert.Equal(t, http.SameSiteLaxMode, opts.SameSite, "original options should be unchanged") + assert.Equal(t, http.SameSiteDefaultMode, newOpts.SameSite, "copy of options should have new value") +} + +func TestOptions_WithSecure(t *testing.T) { + opts := cookie.Options{}.WithSecure(true) + + assert.True(t, opts.Secure) + + opts = cookie.Options{ + Secure: false, + } + newOpts := opts.WithSecure(true) + + assert.False(t, opts.Secure, "original options should be unchanged") + assert.True(t, newOpts.Secure, "copy of options should have new value") +} diff --git a/pkg/router/cookies.go b/pkg/router/cookies.go index d42fdb4..413d03a 100644 --- a/pkg/router/cookies.go +++ b/pkg/router/cookies.go @@ -1,107 +1,36 @@ package router import ( - "encoding/base64" - "encoding/json" "fmt" "net/http" - "time" - "github.com/nais/wonderwall/pkg/openid" + "github.com/nais/wonderwall/pkg/cookie" ) const ( - LoginCookieLifetime = 60 * time.Minute - - SessionCookieNameTemplate = "io.nais.wonderwall.session" - LoginCookieNameTemplate = "io.nais.wonderwall.callback" + SessionCookieName = "io.nais.wonderwall.session" + LoginCookieName = "io.nais.wonderwall.callback" ) -func (h *Handler) GetLoginCookieName() string { - return LoginCookieNameTemplate -} - -func (h *Handler) GetSessionCookieName() string { - return SessionCookieNameTemplate -} - -func (h *Handler) getLoginCookie(r *http.Request) (*openid.LoginCookie, error) { - loginCookieJson, err := h.getEncryptedCookie(r, h.GetLoginCookieName()) - if err != nil { - return nil, err - } - - var loginCookie openid.LoginCookie - err = json.Unmarshal([]byte(loginCookieJson), &loginCookie) - if err != nil { - return nil, err - } - - return &loginCookie, nil -} - -func (h *Handler) setLoginCookie(w http.ResponseWriter, loginCookie *openid.LoginCookie) error { - loginCookieJson, err := json.Marshal(loginCookie) - if err != nil { - return fmt.Errorf("marshalling login cookie: %w", err) - } - - err = h.setEncryptedCookie(w, h.GetLoginCookieName(), string(loginCookieJson), LoginCookieLifetime) +func (h *Handler) setEncryptedCookie(w http.ResponseWriter, key string, plaintext string, opts cookie.Options) error { + encryptedCookie, err := cookie.Make(key, plaintext, opts).Encrypt(h.Crypter) if err != nil { return err } + cookie.Set(w, encryptedCookie) return nil } -func (h *Handler) setEncryptedCookie(w http.ResponseWriter, key string, plaintext string, expiresIn time.Duration) error { - ciphertext, err := h.Crypter.Encrypt([]byte(plaintext)) - if err != nil { - return fmt.Errorf("unable to encrypt cookie '%s': %w", key, err) - } - - http.SetCookie(w, &http.Cookie{ - Expires: time.Now().Add(expiresIn), - HttpOnly: true, - MaxAge: int(expiresIn.Seconds()), - Name: key, - Path: "/", - SameSite: http.SameSiteLaxMode, - Secure: h.SecureCookies, - Value: base64.StdEncoding.EncodeToString(ciphertext), - }) - - return nil -} - -func (h *Handler) getEncryptedCookie(r *http.Request, key string) (string, error) { - encoded, err := r.Cookie(key) +func (h *Handler) getDecryptedCookie(r *http.Request, key string) (string, error) { + encryptedCookie, err := cookie.Get(r, key) if err != nil { return "", fmt.Errorf("no cookie named '%s': %w", key, err) } - ciphertext, err := base64.StdEncoding.DecodeString(encoded.Value) - if err != nil { - return "", fmt.Errorf("cookie named '%s' is not base64 encoded: %w", key, err) - } - - plaintext, err := h.Crypter.Decrypt(ciphertext) - if err != nil { - return "", fmt.Errorf("unable to decrypt cookie '%s': %w", key, err) - } - - return string(plaintext), nil + return encryptedCookie.Decrypt(h.Crypter) } -func (h *Handler) deleteCookie(w http.ResponseWriter, key string) { - expires := time.Now().Add(-7 * 24 * time.Hour) - http.SetCookie(w, &http.Cookie{ - Expires: expires, - HttpOnly: true, - MaxAge: -1, - Name: key, - Path: "/", - SameSite: http.SameSiteLaxMode, - Secure: h.SecureCookies, - }) +func (h *Handler) deleteCookie(w http.ResponseWriter, name string, opts cookie.Options) { + cookie.Clear(w, name, opts) } diff --git a/pkg/router/handler.go b/pkg/router/handler.go index 0e6d292..7bd1cb6 100644 --- a/pkg/router/handler.go +++ b/pkg/router/handler.go @@ -7,20 +7,21 @@ import ( "golang.org/x/oauth2" "github.com/nais/wonderwall/pkg/config" + "github.com/nais/wonderwall/pkg/cookie" "github.com/nais/wonderwall/pkg/crypto" "github.com/nais/wonderwall/pkg/openid" "github.com/nais/wonderwall/pkg/session" ) type Handler struct { - Config config.Config - Crypter crypto.Crypter - OauthConfig oauth2.Config - Provider openid.Provider - SecureCookies bool - Sessions session.Store - lock sync.Mutex - Httplogger zerolog.Logger + Config config.Config + Cookies cookie.Options + Crypter crypto.Crypter + OauthConfig oauth2.Config + Provider openid.Provider + Sessions session.Store + lock sync.Mutex + Httplogger zerolog.Logger } func NewHandler( @@ -41,18 +42,13 @@ func NewHandler( } return &Handler{ - Config: cfg, - Crypter: crypter, - Httplogger: httplogger, - lock: sync.Mutex{}, - OauthConfig: oauthConfig, - Provider: provider, - Sessions: sessionStore, - SecureCookies: true, + Config: cfg, + Cookies: cookie.DefaultOptions(), + Crypter: crypter, + Httplogger: httplogger, + lock: sync.Mutex{}, + OauthConfig: oauthConfig, + Provider: provider, + Sessions: sessionStore, }, nil } - -func (h *Handler) WithSecureCookie(enabled bool) *Handler { - h.SecureCookies = enabled - return h -} diff --git a/pkg/router/handler_callback.go b/pkg/router/handler_callback.go index 020b9ed..6eef211 100644 --- a/pkg/router/handler_callback.go +++ b/pkg/router/handler_callback.go @@ -57,8 +57,7 @@ func (h *Handler) Callback(w http.ResponseWriter, r *http.Request) { return } - // delete login cookie as we no longer need it - h.deleteCookie(w, h.GetLoginCookieName()) + h.clearLoginCookie(w) http.Redirect(w, r, loginCookie.Referer, http.StatusTemporaryRedirect) } diff --git a/pkg/router/handler_frontchannellogout.go b/pkg/router/handler_frontchannellogout.go index 3f9af12..382d51e 100644 --- a/pkg/router/handler_frontchannellogout.go +++ b/pkg/router/handler_frontchannellogout.go @@ -15,7 +15,7 @@ func (h *Handler) FrontChannelLogout(w http.ResponseWriter, r *http.Request) { sid := params.Get("sid") // Unconditionally destroy all local references to the session. - h.deleteCookie(w, h.GetSessionCookieName()) + h.deleteCookie(w, SessionCookieName, h.Cookies) if len(sid) == 0 { log.Info("sid parameter not set in request; ignoring") diff --git a/pkg/router/handler_login.go b/pkg/router/handler_login.go index 9d230ee..1967aa7 100644 --- a/pkg/router/handler_login.go +++ b/pkg/router/handler_login.go @@ -1,14 +1,21 @@ package router import ( + "encoding/json" "errors" "fmt" "net/http" + "time" + "github.com/nais/wonderwall/pkg/cookie" "github.com/nais/wonderwall/pkg/openid" "github.com/nais/wonderwall/pkg/router/request" ) +const ( + LoginCookieLifetime = 1 * time.Hour +) + func (h *Handler) Login(w http.ResponseWriter, r *http.Request) { params, err := openid.GenerateLoginParameters() if err != nil { @@ -29,7 +36,7 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) { return } - err = h.setLoginCookie(w, &openid.LoginCookie{ + err = h.setLoginCookies(w, &openid.LoginCookie{ State: params.State, Nonce: params.Nonce, CodeVerifier: params.CodeVerifier, @@ -42,3 +49,40 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect) } + +func (h *Handler) getLoginCookie(r *http.Request) (*openid.LoginCookie, error) { + loginCookieJson, err := h.getDecryptedCookie(r, LoginCookieName) + if err != nil { + return nil, err + } + + var loginCookie openid.LoginCookie + err = json.Unmarshal([]byte(loginCookieJson), &loginCookie) + if err != nil { + return nil, err + } + + return &loginCookie, nil +} + +func (h *Handler) setLoginCookies(w http.ResponseWriter, loginCookie *openid.LoginCookie) error { + loginCookieJson, err := json.Marshal(loginCookie) + if err != nil { + return fmt.Errorf("marshalling login cookie: %w", err) + } + + opts := h.Cookies.WithExpiresIn(LoginCookieLifetime) + value := string(loginCookieJson) + + err = h.setEncryptedCookie(w, LoginCookieName, value, opts) + if err != nil { + return err + } + + return nil +} + +func (h *Handler) clearLoginCookie(w http.ResponseWriter) { + opts := h.Cookies + cookie.Clear(w, LoginCookieName, opts) +} diff --git a/pkg/router/handler_logout.go b/pkg/router/handler_logout.go index ff2af1d..47148aa 100644 --- a/pkg/router/handler_logout.go +++ b/pkg/router/handler_logout.go @@ -28,7 +28,7 @@ func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) { } } - h.deleteCookie(w, h.GetSessionCookieName()) + h.deleteCookie(w, SessionCookieName, h.Cookies) v := u.Query() @@ -37,9 +37,10 @@ func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) { v.Add("post_logout_redirect_uri", postLogoutURI) } - if len(idToken) != 0 { + if len(idToken) > 0 { v.Add("id_token_hint", idToken) } + u.RawQuery = v.Encode() http.Redirect(w, r, u.String(), http.StatusTemporaryRedirect) diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index 97ca7e9..8093ef5 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -38,7 +38,9 @@ func newHandler(provider openid.Provider) *router.Handler { if err != nil { panic(err) } - return h.WithSecureCookie(false) + + h.Cookies = h.Cookies.WithSecure(false) + return h } func TestHandler_Login(t *testing.T) { @@ -65,7 +67,7 @@ func TestHandler_Login(t *testing.T) { defer resp.Body.Close() cookies := client.Jar.Cookies(loginURL) - loginCookie := getCookieFromJar(h.GetLoginCookieName(), cookies) + loginCookie := getCookieFromJar(router.LoginCookieName, cookies) assert.NotNil(t, loginCookie) location := resp.Header.Get("location") @@ -122,8 +124,8 @@ func TestHandler_Callback_and_Logout(t *testing.T) { defer resp.Body.Close() cookies := client.Jar.Cookies(loginURL) - sessionCookie := getCookieFromJar(h.GetSessionCookieName(), cookies) - loginCookie := getCookieFromJar(h.GetLoginCookieName(), cookies) + sessionCookie := getCookieFromJar(router.SessionCookieName, cookies) + loginCookie := getCookieFromJar(router.LoginCookieName, cookies) assert.Nil(t, sessionCookie) assert.NotNil(t, loginCookie) @@ -150,8 +152,8 @@ func TestHandler_Callback_and_Logout(t *testing.T) { assert.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) cookies = client.Jar.Cookies(callbackURL) - sessionCookie = getCookieFromJar(h.GetSessionCookieName(), cookies) - loginCookie = getCookieFromJar(h.GetLoginCookieName(), cookies) + sessionCookie = getCookieFromJar(router.SessionCookieName, cookies) + loginCookie = getCookieFromJar(router.LoginCookieName, cookies) assert.NotNil(t, sessionCookie) assert.Nil(t, loginCookie) @@ -166,7 +168,7 @@ func TestHandler_Callback_and_Logout(t *testing.T) { defer resp.Body.Close() cookies = client.Jar.Cookies(logoutURL) - sessionCookie = getCookieFromJar(h.GetSessionCookieName(), cookies) + sessionCookie = getCookieFromJar(router.SessionCookieName, cookies) assert.Nil(t, sessionCookie) @@ -232,7 +234,7 @@ func TestHandler_FrontChannelLogout(t *testing.T) { assert.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) cookies := client.Jar.Cookies(callbackURL) - sessionCookie := getCookieFromJar(h.GetSessionCookieName(), cookies) + sessionCookie := getCookieFromJar(router.SessionCookieName, cookies) assert.NotNil(t, sessionCookie) diff --git a/pkg/router/session.go b/pkg/router/session.go index 34d7c37..71d5e20 100644 --- a/pkg/router/session.go +++ b/pkg/router/session.go @@ -25,7 +25,7 @@ func (h *Handler) localSessionID(sid string) string { } func (h *Handler) getSessionFromCookie(w http.ResponseWriter, r *http.Request) (*session.Data, error) { - sessionID, err := h.getEncryptedCookie(r, h.GetSessionCookieName()) + sessionID, err := h.getDecryptedCookie(r, SessionCookieName) if err != nil { return nil, fmt.Errorf("no session cookie: %w", err) } @@ -80,7 +80,9 @@ func (h *Handler) createSession(w http.ResponseWriter, r *http.Request, external return fmt.Errorf("getting access token lifetime: %w", err) } - err = h.setEncryptedCookie(w, h.GetSessionCookieName(), sessionID, sessionLifetime) + opts := h.Cookies.WithExpiresIn(sessionLifetime) + + err = h.setEncryptedCookie(w, SessionCookieName, sessionID, opts) if err != nil { return fmt.Errorf("setting session cookie: %w", err) } diff --git a/pkg/router/session_fallback.go b/pkg/router/session_fallback.go index 1a71586..c71867f 100644 --- a/pkg/router/session_fallback.go +++ b/pkg/router/session_fallback.go @@ -10,29 +10,31 @@ import ( ) func (h *Handler) SessionFallbackExternalIDCookieName() string { - return h.GetSessionCookieName() + ".1" + return SessionCookieName + ".1" } func (h *Handler) SessionFallbackIDTokenCookieName() string { - return h.GetSessionCookieName() + ".2" + return SessionCookieName + ".2" } func (h *Handler) SessionFallbackAccessTokenCookieName() string { - return h.GetSessionCookieName() + ".3" + return SessionCookieName + ".3" } func (h *Handler) SetSessionFallback(w http.ResponseWriter, data *session.Data, expiresIn time.Duration) error { - err := h.setEncryptedCookie(w, h.SessionFallbackExternalIDCookieName(), data.ExternalSessionID, expiresIn) + opts := h.Cookies.WithExpiresIn(expiresIn) + + err := h.setEncryptedCookie(w, h.SessionFallbackExternalIDCookieName(), data.ExternalSessionID, opts) if err != nil { return fmt.Errorf("setting session id fallback cookie: %w", err) } - err = h.setEncryptedCookie(w, h.SessionFallbackAccessTokenCookieName(), data.AccessToken, expiresIn) + err = h.setEncryptedCookie(w, h.SessionFallbackAccessTokenCookieName(), data.AccessToken, opts) if err != nil { return fmt.Errorf("setting session id_token fallback cookie: %w", err) } - err = h.setEncryptedCookie(w, h.SessionFallbackIDTokenCookieName(), data.IDToken, expiresIn) + err = h.setEncryptedCookie(w, h.SessionFallbackIDTokenCookieName(), data.IDToken, opts) if err != nil { return fmt.Errorf("setting session access_token fallback cookie: %w", err) } @@ -41,17 +43,17 @@ func (h *Handler) SetSessionFallback(w http.ResponseWriter, data *session.Data, } func (h *Handler) GetSessionFallback(r *http.Request) (*session.Data, error) { - externalSessionID, err := h.getEncryptedCookie(r, h.SessionFallbackExternalIDCookieName()) + externalSessionID, err := h.getDecryptedCookie(r, h.SessionFallbackExternalIDCookieName()) if err != nil { return nil, fmt.Errorf("reading session ID from fallback cookie: %w", err) } - idToken, err := h.getEncryptedCookie(r, h.SessionFallbackIDTokenCookieName()) + idToken, err := h.getDecryptedCookie(r, h.SessionFallbackIDTokenCookieName()) if err != nil { return nil, fmt.Errorf("reading id_token from fallback cookie: %w", err) } - accessToken, err := h.getEncryptedCookie(r, h.SessionFallbackAccessTokenCookieName()) + accessToken, err := h.getDecryptedCookie(r, h.SessionFallbackAccessTokenCookieName()) if err != nil { return nil, fmt.Errorf("reading access_token from fallback cookie: %w", err) } @@ -66,7 +68,7 @@ func (h *Handler) DeleteSessionFallback(w http.ResponseWriter, r *http.Request) return } - h.deleteCookie(w, cookieName) + h.deleteCookie(w, cookieName, h.Cookies) } deleteIfNotFound(h, w, h.SessionFallbackAccessTokenCookieName())