@@ -278,4 +278,263 @@ var _ = Describe("CSRF Cookie Tests", func() {
282+ Context("Test Cookie SameSite", func() {
283+ var req *http.Request
284+ var cookieOpts *options.Cookie
286+ testNow := time.Unix(nowEpoch, 0)
289+ // we need to reset the time to ensure the cookie is valid
290+ privateCSRF.clock = time.Now
292+ req = &http.Request{
293+ Method: http.MethodGet,
304+ cookieOpts = &options.Cookie{
306+ Secret: cookieSecret,
307+ Domains: []string{cookieDomain},
312+ CSRFPerRequest: false,
313+ CSRFExpire: time.Hour,
317+ It("Call SetCookie when CSRF SameSite is not defined. Expected result: CSRF cookie SameSite is the same as session cookie.", func() {
319+ cookieOpts.SameSite = sameSiteLax
320+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
321+ rw := httptest.NewRecorder()
322+ CSRF.(*csrf).clock = func() time.Time { return testNow }
325+ _, err := CSRF.SetCookie(rw, req)
328+ Expect(err).ToNot(HaveOccurred())
329+ Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
331+ "; Path=%s; Domain=%s; Max-Age=%d; HttpOnly; Secure; SameSite=Lax",
334+ int(cookieOpts.CSRFExpire.Seconds()),
339+ It("Call SetCookie when CSRF SameSite is an empty string. Expected result: CSRF cookie SameSite is the same as session cookie.", func() {
341+ cookieOpts.SameSite = sameSiteLax
342+ cookieOpts.CSRFSameSite = ""
343+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
344+ rw := httptest.NewRecorder()
345+ CSRF.(*csrf).clock = func() time.Time { return testNow }
348+ _, err := CSRF.SetCookie(rw, req)
351+ Expect(err).ToNot(HaveOccurred())
352+ Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
354+ "; Path=%s; Domain=%s; Max-Age=%d; HttpOnly; Secure; SameSite=Lax",
357+ int(cookieOpts.CSRFExpire.Seconds()),
362+ It("Call SetCookie when CSRF SameSite is 'none'. Expected result: CSRF cookie SameSite is None.", func() {
364+ cookieOpts.SameSite = sameSiteLax
365+ cookieOpts.CSRFSameSite = sameSiteNone
366+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
367+ rw := httptest.NewRecorder()
368+ CSRF.(*csrf).clock = func() time.Time { return testNow }
371+ _, err := CSRF.SetCookie(rw, req)
374+ Expect(err).ToNot(HaveOccurred())
375+ Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
377+ "; Path=%s; Domain=%s; Max-Age=%d; HttpOnly; Secure; SameSite=None",
380+ int(cookieOpts.CSRFExpire.Seconds()),
385+ It("Call SetCookie when CSRF SameSite is 'strict'. Expected result: CSRF cookie SameSite is Strict.", func() {
387+ cookieOpts.SameSite = sameSiteLax
388+ cookieOpts.CSRFSameSite = sameSiteStrict
389+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
390+ rw := httptest.NewRecorder()
391+ CSRF.(*csrf).clock = func() time.Time { return testNow }
394+ _, err := CSRF.SetCookie(rw, req)
397+ Expect(err).ToNot(HaveOccurred())
398+ Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
400+ "; Path=%s; Domain=%s; Max-Age=%d; HttpOnly; Secure; SameSite=Strict",
403+ int(cookieOpts.CSRFExpire.Seconds()),
408+ It("Call SetCookie when CSRF SameSite is 'lax'. Expected result: CSRF cookie SameSite is Lax.", func() {
410+ cookieOpts.SameSite = sameSiteStrict
411+ cookieOpts.CSRFSameSite = sameSiteLax
412+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
413+ rw := httptest.NewRecorder()
414+ CSRF.(*csrf).clock = func() time.Time { return testNow }
417+ _, err := CSRF.SetCookie(rw, req)
420+ Expect(err).ToNot(HaveOccurred())
421+ Expect(rw.Header().Get("Set-Cookie")).To(ContainSubstring(
423+ "; Path=%s; Domain=%s; Max-Age=%d; HttpOnly; Secure; SameSite=Lax",
426+ int(cookieOpts.CSRFExpire.Seconds()),
431+ It("Call ClearCookie when CSRF SameSite is not defined. Expected result: CSRF cookie SameSite is the same as session cookie.", func() {
433+ cookieOpts.SameSite = sameSiteLax
434+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
435+ rw := httptest.NewRecorder()
436+ CSRF.(*csrf).clock = func() time.Time { return testNow }
439+ CSRF.ClearCookie(rw, req)
442+ Expect(rw.Header().Get("Set-Cookie")).To(Equal(
444+ "%s=; Path=%s; Domain=%s; Max-Age=0; HttpOnly; Secure; SameSite=Lax",
445+ CSRF.(*csrf).cookieName(),
452+ It("Call ClearCookie when CSRF SameSite is an empty string. Expected result: CSRF cookie SameSite is the same as session cookie.", func() {
454+ cookieOpts.SameSite = sameSiteLax
455+ cookieOpts.CSRFSameSite = ""
456+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
457+ rw := httptest.NewRecorder()
458+ CSRF.(*csrf).clock = func() time.Time { return testNow }
461+ CSRF.ClearCookie(rw, req)
464+ Expect(rw.Header().Get("Set-Cookie")).To(Equal(
466+ "%s=; Path=%s; Domain=%s; Max-Age=0; HttpOnly; Secure; SameSite=Lax",
467+ CSRF.(*csrf).cookieName(),
474+ It("Call ClearCookie when CSRF SameSite is 'none'. Expected result: CSRF cookie SameSite is None.", func() {
476+ cookieOpts.SameSite = sameSiteLax
477+ cookieOpts.CSRFSameSite = sameSiteNone
478+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
479+ rw := httptest.NewRecorder()
480+ CSRF.(*csrf).clock = func() time.Time { return testNow }
483+ CSRF.ClearCookie(rw, req)
486+ Expect(rw.Header().Get("Set-Cookie")).To(Equal(
488+ "%s=; Path=%s; Domain=%s; Max-Age=0; HttpOnly; Secure; SameSite=None",
489+ CSRF.(*csrf).cookieName(),
496+ It("Call ClearCookie when CSRF SameSite is 'strict'. Expected result: CSRF cookie SameSite is Strict.", func() {
498+ cookieOpts.SameSite = sameSiteLax
499+ cookieOpts.CSRFSameSite = sameSiteStrict
500+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
501+ rw := httptest.NewRecorder()
502+ CSRF.(*csrf).clock = func() time.Time { return testNow }
505+ CSRF.ClearCookie(rw, req)
508+ Expect(rw.Header().Get("Set-Cookie")).To(Equal(
510+ "%s=; Path=%s; Domain=%s; Max-Age=0; HttpOnly; Secure; SameSite=Strict",
511+ CSRF.(*csrf).cookieName(),
518+ It("Call ClearCookie when CSRF SameSite is 'lax'. Expected result: CSRF cookie SameSite is Lax.", func() {
520+ cookieOpts.SameSite = sameSiteStrict
521+ cookieOpts.CSRFSameSite = sameSiteLax
522+ CSRF, _ := NewCSRF(cookieOpts, "verifier")
523+ rw := httptest.NewRecorder()
524+ CSRF.(*csrf).clock = func() time.Time { return testNow }
527+ CSRF.ClearCookie(rw, req)
530+ Expect(rw.Header().Get("Set-Cookie")).To(Equal(
532+ "%s=; Path=%s; Domain=%s; Max-Age=0; HttpOnly; Secure; SameSite=Lax",
533+ CSRF.(*csrf).cookieName(),