Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion token/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ func (j *Service) IsExpired(claims Claims) bool {

// Reset token's cookies
func (j *Service) Reset(w http.ResponseWriter) {
jwtCookie := http.Cookie{Name: j.JWTCookieName, Value: "", HttpOnly: false, Path: "/", Domain: j.JWTCookieDomain, //nolint:gosec // expired removal cookie, carries no value
// HttpOnly as on the live cookie: a browser rejects an expiry for a __Http- prefixed name without it
jwtCookie := http.Cookie{Name: j.JWTCookieName, Value: "", HttpOnly: true, Path: "/", Domain: j.JWTCookieDomain, //nolint:gosec // Secure and SameSite come from service config
MaxAge: -1, Expires: time.Unix(0, 0), Secure: j.SecureCookies, SameSite: j.SameSite, Partitioned: j.PartitionedCookies}
http.SetCookie(w, &jwtCookie)

Expand Down
10 changes: 5 additions & 5 deletions token/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,15 +280,15 @@ func TestJWT_CookieAttributesFromOpts(t *testing.T) {

t.Run("reset", func(t *testing.T) {
// the removal pair has to repeat these attributes, though not because they are part of
// the cookie's identity: that is name, domain and path alone, which is why Reset writing
// HttpOnly false over a cookie Set wrote HttpOnly true still replaces it. The reason is
// that Chrome and Firefox reject SameSite=None without Secure outright, and a removal
// cookie the browser discards leaves the original in place
// the cookie's identity: that is name, domain and path alone. The reason is that Chrome and
// Firefox reject SameSite=None without Secure outright, and a removal cookie the browser
// discards leaves the original in place
rr := httptest.NewRecorder()
j.Reset(rr)

cookies := rr.Result().Cookies()
checkPair(t, cookies)
assert.True(t, cookies[0].HttpOnly, "a browser rejects a __Http- prefixed removal cookie without HttpOnly")
for _, c := range cookies {
assert.Empty(t, c.Value, "%s still carries a value", c.Name)
assert.Equal(t, -1, c.MaxAge, "%s does not expire", c.Name)
Expand Down Expand Up @@ -645,7 +645,7 @@ func TestJWT_Reset(t *testing.T) {
require.Nil(t, err)
assert.Equal(t, 200, resp.StatusCode)

assert.Equal(t, "jc1=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0", resp.Header.Get("Set-Cookie"))
assert.Equal(t, "jc1=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; HttpOnly", resp.Header.Get("Set-Cookie"))
assert.Equal(t, "0", resp.Header.Get("Content-Length"))
}

Expand Down
3 changes: 2 additions & 1 deletion v2/token/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,8 @@ func (j *Service) IsExpired(claims Claims) bool {

// Reset token's cookies
func (j *Service) Reset(w http.ResponseWriter) {
jwtCookie := http.Cookie{Name: j.JWTCookieName, Value: "", HttpOnly: false, Path: "/", Domain: j.JWTCookieDomain, //nolint:gosec // expired removal cookie, carries no value
// HttpOnly as on the live cookie: a browser rejects an expiry for a __Http- prefixed name without it
jwtCookie := http.Cookie{Name: j.JWTCookieName, Value: "", HttpOnly: true, Path: "/", Domain: j.JWTCookieDomain, //nolint:gosec // Secure and SameSite come from service config
MaxAge: -1, Expires: time.Unix(0, 0), Secure: j.SecureCookies, SameSite: j.SameSite, Partitioned: j.PartitionedCookies}
http.SetCookie(w, &jwtCookie)

Expand Down
10 changes: 5 additions & 5 deletions v2/token/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,15 +280,15 @@ func TestJWT_CookieAttributesFromOpts(t *testing.T) {

t.Run("reset", func(t *testing.T) {
// the removal pair has to repeat these attributes, though not because they are part of
// the cookie's identity: that is name, domain and path alone, which is why Reset writing
// HttpOnly false over a cookie Set wrote HttpOnly true still replaces it. The reason is
// that Chrome and Firefox reject SameSite=None without Secure outright, and a removal
// cookie the browser discards leaves the original in place
// the cookie's identity: that is name, domain and path alone. The reason is that Chrome and
// Firefox reject SameSite=None without Secure outright, and a removal cookie the browser
// discards leaves the original in place
rr := httptest.NewRecorder()
j.Reset(rr)

cookies := rr.Result().Cookies()
checkPair(t, cookies)
assert.True(t, cookies[0].HttpOnly, "a browser rejects a __Http- prefixed removal cookie without HttpOnly")
for _, c := range cookies {
assert.Empty(t, c.Value, "%s still carries a value", c.Name)
assert.Equal(t, -1, c.MaxAge, "%s does not expire", c.Name)
Expand Down Expand Up @@ -645,7 +645,7 @@ func TestJWT_Reset(t *testing.T) {
require.Nil(t, err)
assert.Equal(t, 200, resp.StatusCode)

assert.Equal(t, "jc1=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0", resp.Header.Get("Set-Cookie"))
assert.Equal(t, "jc1=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; HttpOnly", resp.Header.Get("Set-Cookie"))
assert.Equal(t, "0", resp.Header.Get("Content-Length"))
}

Expand Down
Loading