fix: use GetSecret() in ticket.go makeCookie to respect cookie-secret-file (#3228)

* fix: use GetSecret() in ticket.go makeCookie

The makeCookie method in ticket.go was using t.options.Secret directly, which
meant cookie-secret-file was not being respected. Updated to use GetSecret()
which handles both cookie-secret and cookie-secret-file properly.

Also added test coverage for cookie-secret-file functionality.

Fixes #3224

Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>

* docs: update CHANGELOG.md for cookie-secret-file fix

Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>

* correct PR link and undo file formatting

Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>

* fix: error wrapping

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: stagswtf <142280349+stagswtf@users.noreply.github.com>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
This commit is contained in:
stagswtf 2025-10-28 00:37:25 -07:00 committed by GitHub
parent c0a087d7f2
commit 51e80f24ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 48 additions and 4 deletions

View File

@ -8,6 +8,8 @@
## Changes since v7.12.0
- [#3228](https://github.com/oauth2-proxy/oauth2-proxy/pull/3228) fix: use GetSecret() in ticket.go makeCookie to respect cookie-secret-file (@stagswtf)
# V7.12.0
## Release Highlights

View File

@ -233,12 +233,17 @@ func (t *ticket) clearCookie(rw http.ResponseWriter, req *http.Request) {
// makeCookie makes a cookie, signing the value if present
func (t *ticket) makeCookie(req *http.Request, value string, expires time.Duration, now time.Time) (*http.Cookie, error) {
if value != "" {
var err error
value, err = encryption.SignedValue(t.options.Secret, t.options.Name, []byte(value), now)
secret, err := t.options.GetSecret()
if err != nil {
return nil, err
return nil, fmt.Errorf("retrieving secret failed: %w", err)
}
value, err = encryption.SignedValue(secret, t.options.Name, []byte(value), now)
if err != nil {
return nil, fmt.Errorf("signing cookie value failed: %w", err)
}
}
return cookies.MakeCookieFromOptions(
req,
t.options.Name,

View File

@ -4,6 +4,7 @@ import (
"crypto/rand"
"net/http"
"net/http/httptest"
"os"
"strconv"
"strings"
"time"
@ -133,6 +134,42 @@ func RunSessionStoreTests(newSS NewSessionStoreFunc, persistentFastForward Persi
PersistentSessionStoreInterfaceTests(&input)
}
})
Context("with cookie secret file", func() {
var tmpfile *os.File
var err error
BeforeEach(func() {
tmpfile, err = os.CreateTemp("", "cookie-secret-test")
secretBytes := make([]byte, 32)
tmpfile.Write(secretBytes)
tmpfile.Close()
input.cookieOpts = &options.Cookie{
Name: "_oauth2_proxy_file",
Path: "/",
Expire: time.Duration(168) * time.Hour,
Refresh: time.Duration(1) * time.Hour,
Secure: true,
HTTPOnly: true,
SameSite: "",
Secret: "",
SecretFile: tmpfile.Name(),
}
ss, err = newSS(opts, input.cookieOpts)
Expect(err).ToNot(HaveOccurred())
})
AfterEach(func() {
if tmpfile != nil {
os.Remove(tmpfile.Name())
}
})
SessionStoreInterfaceTests(&input)
if persistentFastForward != nil {
PersistentSessionStoreInterfaceTests(&input)
}
})
})
}