mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-05-21 22:33:38 +02:00
Merge pull request #2697 from matpen-wi/feat/max-age-instead-of-expires
pkg/cookies: use 'Max-Age' instead of 'Expires' for cookie expiration
This commit is contained in:
commit
a25fef7cbf
@ -9,6 +9,7 @@
|
|||||||
## Changes since v7.8.1
|
## Changes since v7.8.1
|
||||||
|
|
||||||
- [#2927](https://github.com/oauth2-proxy/oauth2-proxy/pull/2927) chore(deps/build): bump golang to 1.23 and use go.mod as single point of truth for all build files (@tuunit)
|
- [#2927](https://github.com/oauth2-proxy/oauth2-proxy/pull/2927) chore(deps/build): bump golang to 1.23 and use go.mod as single point of truth for all build files (@tuunit)
|
||||||
|
- [#2697](https://github.com/oauth2-proxy/oauth2-proxy/pull/2697) Use `Max-Age` instead of `Expires` for cookie expiration (@matpen-wi)
|
||||||
|
|
||||||
# V7.8.1
|
# V7.8.1
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// MakeCookieFromOptions constructs a cookie based on the given *options.CookieOptions,
|
// MakeCookieFromOptions constructs a cookie based on the given *options.CookieOptions,
|
||||||
// value and creation time
|
// value and creation time
|
||||||
func MakeCookieFromOptions(req *http.Request, name string, value string, opts *options.Cookie, expiration time.Duration, now time.Time) *http.Cookie {
|
func MakeCookieFromOptions(req *http.Request, name string, value string, opts *options.Cookie, expiration time.Duration) *http.Cookie {
|
||||||
domain := GetCookieDomain(req, opts.Domains)
|
domain := GetCookieDomain(req, opts.Domains)
|
||||||
// If nothing matches, create the cookie with the shortest domain
|
// If nothing matches, create the cookie with the shortest domain
|
||||||
if domain == "" && len(opts.Domains) > 0 {
|
if domain == "" && len(opts.Domains) > 0 {
|
||||||
@ -35,8 +35,10 @@ func MakeCookieFromOptions(req *http.Request, name string, value string, opts *o
|
|||||||
SameSite: ParseSameSite(opts.SameSite),
|
SameSite: ParseSameSite(opts.SameSite),
|
||||||
}
|
}
|
||||||
|
|
||||||
if expiration != time.Duration(0) {
|
if expiration > time.Duration(0) {
|
||||||
c.Expires = now.Add(expiration)
|
c.MaxAge = int(expiration.Seconds())
|
||||||
|
} else if expiration < time.Duration(0) {
|
||||||
|
c.MaxAge = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
warnInvalidDomain(c, req)
|
warnInvalidDomain(c, req)
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package cookies
|
package cookies
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
@ -28,8 +26,3 @@ func TestProviderSuite(t *testing.T) {
|
|||||||
RegisterFailHandler(Fail)
|
RegisterFailHandler(Fail)
|
||||||
RunSpecs(t, "Cookies")
|
RunSpecs(t, "Cookies")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCookieExpires(exp time.Time) string {
|
|
||||||
var buf [len(http.TimeFormat)]byte
|
|
||||||
return string(exp.UTC().AppendFormat(buf[:0], http.TimeFormat))
|
|
||||||
}
|
|
||||||
|
@ -87,7 +87,7 @@ var _ = Describe("Cookie Tests", func() {
|
|||||||
opts options.Cookie
|
opts options.Cookie
|
||||||
expiration time.Duration
|
expiration time.Duration
|
||||||
now time.Time
|
now time.Time
|
||||||
expectedOutput time.Time
|
expectedOutput int
|
||||||
}
|
}
|
||||||
|
|
||||||
validName := "_oauth2_proxy"
|
validName := "_oauth2_proxy"
|
||||||
@ -95,7 +95,7 @@ var _ = Describe("Cookie Tests", func() {
|
|||||||
domains := []string{"www.cookies.test"}
|
domains := []string{"www.cookies.test"}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
var expectedExpires time.Time
|
var expectedMaxAge int
|
||||||
|
|
||||||
DescribeTable("should return cookies with or without expiration",
|
DescribeTable("should return cookies with or without expiration",
|
||||||
func(in makeCookieFromOptionsTableInput) {
|
func(in makeCookieFromOptionsTableInput) {
|
||||||
@ -106,7 +106,7 @@ var _ = Describe("Cookie Tests", func() {
|
|||||||
)
|
)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(MakeCookieFromOptions(req, in.name, in.value, &in.opts, in.expiration, in.now).Expires).To(Equal(in.expectedOutput))
|
Expect(MakeCookieFromOptions(req, in.name, in.value, &in.opts, in.expiration).MaxAge).To(Equal(in.expectedOutput))
|
||||||
},
|
},
|
||||||
Entry("persistent cookie", makeCookieFromOptionsTableInput{
|
Entry("persistent cookie", makeCookieFromOptionsTableInput{
|
||||||
host: "www.cookies.test",
|
host: "www.cookies.test",
|
||||||
@ -125,7 +125,26 @@ var _ = Describe("Cookie Tests", func() {
|
|||||||
},
|
},
|
||||||
expiration: 15 * time.Minute,
|
expiration: 15 * time.Minute,
|
||||||
now: now,
|
now: now,
|
||||||
expectedOutput: now.Add(15 * time.Minute),
|
expectedOutput: int((15 * time.Minute).Seconds()),
|
||||||
|
}),
|
||||||
|
Entry("persistent cookie to be cleared", makeCookieFromOptionsTableInput{
|
||||||
|
host: "www.cookies.test",
|
||||||
|
name: validName,
|
||||||
|
value: "1",
|
||||||
|
opts: options.Cookie{
|
||||||
|
Name: validName,
|
||||||
|
Secret: validSecret,
|
||||||
|
Domains: domains,
|
||||||
|
Path: "",
|
||||||
|
Expire: time.Hour * -1,
|
||||||
|
Refresh: 15 * time.Minute,
|
||||||
|
Secure: true,
|
||||||
|
HTTPOnly: false,
|
||||||
|
SameSite: "",
|
||||||
|
},
|
||||||
|
expiration: time.Hour * -1,
|
||||||
|
now: now,
|
||||||
|
expectedOutput: -1,
|
||||||
}),
|
}),
|
||||||
Entry("session cookie", makeCookieFromOptionsTableInput{
|
Entry("session cookie", makeCookieFromOptionsTableInput{
|
||||||
host: "www.cookies.test",
|
host: "www.cookies.test",
|
||||||
@ -144,7 +163,7 @@ var _ = Describe("Cookie Tests", func() {
|
|||||||
},
|
},
|
||||||
expiration: 0,
|
expiration: 0,
|
||||||
now: now,
|
now: now,
|
||||||
expectedOutput: expectedExpires,
|
expectedOutput: expectedMaxAge,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -145,7 +145,6 @@ func (c *csrf) SetCookie(rw http.ResponseWriter, req *http.Request) (*http.Cooki
|
|||||||
encoded,
|
encoded,
|
||||||
c.cookieOpts,
|
c.cookieOpts,
|
||||||
c.cookieOpts.CSRFExpire,
|
c.cookieOpts.CSRFExpire,
|
||||||
c.time.Now(),
|
|
||||||
)
|
)
|
||||||
http.SetCookie(rw, cookie)
|
http.SetCookie(rw, cookie)
|
||||||
|
|
||||||
@ -160,7 +159,6 @@ func (c *csrf) ClearCookie(rw http.ResponseWriter, req *http.Request) {
|
|||||||
"",
|
"",
|
||||||
c.cookieOpts,
|
c.cookieOpts,
|
||||||
time.Hour*-1,
|
time.Hour*-1,
|
||||||
c.time.Now(),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,10 +159,10 @@ var _ = Describe("CSRF Cookie with non-fixed name Tests", func() {
|
|||||||
))
|
))
|
||||||
Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
|
Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"; Path=%s; Domain=%s; Expires=%s; HttpOnly; Secure",
|
"; Path=%s; Domain=%s; Max-Age=%d; HttpOnly; Secure",
|
||||||
cookiePath,
|
cookiePath,
|
||||||
cookieDomain,
|
cookieDomain,
|
||||||
testCookieExpires(testNow.Add(cookieOpts.CSRFExpire)),
|
int(cookieOpts.CSRFExpire.Seconds()),
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
@ -176,11 +176,10 @@ var _ = Describe("CSRF Cookie with non-fixed name Tests", func() {
|
|||||||
|
|
||||||
Expect(rw.Header().Get("Set-Cookie")).To(Equal(
|
Expect(rw.Header().Get("Set-Cookie")).To(Equal(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"%s=; Path=%s; Domain=%s; Expires=%s; HttpOnly; Secure",
|
"%s=; Path=%s; Domain=%s; Max-Age=0; HttpOnly; Secure",
|
||||||
privateCSRF.cookieName(),
|
privateCSRF.cookieName(),
|
||||||
cookiePath,
|
cookiePath,
|
||||||
cookieDomain,
|
cookieDomain,
|
||||||
testCookieExpires(testNow.Add(time.Hour*-1)),
|
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -161,10 +161,10 @@ var _ = Describe("CSRF Cookie Tests", func() {
|
|||||||
))
|
))
|
||||||
Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
|
Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"; Path=%s; Domain=%s; Expires=%s; HttpOnly; Secure",
|
"; Path=%s; Domain=%s; Max-Age=%d; HttpOnly; Secure",
|
||||||
cookiePath,
|
cookiePath,
|
||||||
cookieDomain,
|
cookieDomain,
|
||||||
testCookieExpires(testNow.Add(cookieOpts.CSRFExpire)),
|
int(cookieOpts.CSRFExpire.Seconds()),
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
@ -239,11 +239,10 @@ var _ = Describe("CSRF Cookie Tests", func() {
|
|||||||
|
|
||||||
Expect(rw.Header().Get("Set-Cookie")).To(Equal(
|
Expect(rw.Header().Get("Set-Cookie")).To(Equal(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"%s=; Path=%s; Domain=%s; Expires=%s; HttpOnly; Secure",
|
"%s=; Path=%s; Domain=%s; Max-Age=0; HttpOnly; Secure",
|
||||||
privateCSRF.cookieName(),
|
privateCSRF.cookieName(),
|
||||||
cookiePath,
|
cookiePath,
|
||||||
cookieDomain,
|
cookieDomain,
|
||||||
testCookieExpires(testNow.Add(time.Hour*-1)),
|
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -74,7 +74,7 @@ func (s *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) error {
|
|||||||
|
|
||||||
for _, c := range req.Cookies() {
|
for _, c := range req.Cookies() {
|
||||||
if cookieNameRegex.MatchString(c.Name) {
|
if cookieNameRegex.MatchString(c.Name) {
|
||||||
clearCookie := s.makeCookie(req, c.Name, "", time.Hour*-1, time.Now())
|
clearCookie := s.makeCookie(req, c.Name, "", time.Hour*-1)
|
||||||
|
|
||||||
http.SetCookie(rw, clearCookie)
|
http.SetCookie(rw, clearCookie)
|
||||||
}
|
}
|
||||||
@ -126,21 +126,20 @@ func (s *SessionStore) makeSessionCookie(req *http.Request, value []byte, now ti
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c := s.makeCookie(req, s.Cookie.Name, strValue, s.Cookie.Expire, now)
|
c := s.makeCookie(req, s.Cookie.Name, strValue, s.Cookie.Expire)
|
||||||
if len(c.String()) > maxCookieLength {
|
if len(c.String()) > maxCookieLength {
|
||||||
return splitCookie(c), nil
|
return splitCookie(c), nil
|
||||||
}
|
}
|
||||||
return []*http.Cookie{c}, nil
|
return []*http.Cookie{c}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionStore) makeCookie(req *http.Request, name string, value string, expiration time.Duration, now time.Time) *http.Cookie {
|
func (s *SessionStore) makeCookie(req *http.Request, name string, value string, expiration time.Duration) *http.Cookie {
|
||||||
return pkgcookies.MakeCookieFromOptions(
|
return pkgcookies.MakeCookieFromOptions(
|
||||||
req,
|
req,
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
s.Cookie,
|
s.Cookie,
|
||||||
expiration,
|
expiration,
|
||||||
now,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,6 @@ func (t *ticket) clearCookie(rw http.ResponseWriter, req *http.Request) {
|
|||||||
"",
|
"",
|
||||||
t.options,
|
t.options,
|
||||||
time.Hour*-1,
|
time.Hour*-1,
|
||||||
time.Now(),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +241,6 @@ func (t *ticket) makeCookie(req *http.Request, value string, expires time.Durati
|
|||||||
value,
|
value,
|
||||||
t.options,
|
t.options,
|
||||||
expires,
|
expires,
|
||||||
now,
|
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ func SessionStoreInterfaceTests(in *testInput) {
|
|||||||
broken := "BrokenSessionFromADifferentSessionImplementation"
|
broken := "BrokenSessionFromADifferentSessionImplementation"
|
||||||
value, err := encryption.SignedValue(in.cookieOpts.Secret, in.cookieOpts.Name, []byte(broken), time.Now())
|
value, err := encryption.SignedValue(in.cookieOpts.Secret, in.cookieOpts.Name, []byte(broken), time.Now())
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
cookie := cookiesapi.MakeCookieFromOptions(in.request, in.cookieOpts.Name, value, in.cookieOpts, in.cookieOpts.Expire, time.Now())
|
cookie := cookiesapi.MakeCookieFromOptions(in.request, in.cookieOpts.Name, value, in.cookieOpts, in.cookieOpts.Expire)
|
||||||
in.request.AddCookie(cookie)
|
in.request.AddCookie(cookie)
|
||||||
|
|
||||||
err = in.ss().Save(in.response, in.request, in.session)
|
err = in.ss().Save(in.response, in.request, in.session)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user