From b9e295d24fd67acfbd6d844fbd3030fba0334ee2 Mon Sep 17 00:00:00 2001 From: GTVJ Date: Fri, 26 Apr 2024 14:52:19 +0100 Subject: [PATCH 1/6] AUT-2733: Set consent cookie HttpOnly attribute to false The HttpOnly attribute of the `cookie_preferences_set` cookie was set to true in commit c2fbdc under AUT-1985 to address concerns from an IT Health Check linked to in AUT-1949. The IT Health Check stated: "By acquiring another user's session cookie value, an attacker may be able to connect to the application as that user." and "Cookies within the application were found to lack the Secure and HttpOnly flags, leaving it at risk of compromise. The cookies were identified as not being responsible for controlling user sessions for the application" Subsequent testing has revealed the cookie banner does not function as expected where the `cookie_preferences_set` is sent by the server with a HttpOnly attribute. This is because the cookie banner functionality relies on JavaScript to update the cookie in response to user actions. --- src/components/authorize/authorize-controller.ts | 2 +- src/components/common/cookies/cookies-controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/authorize/authorize-controller.ts b/src/components/authorize/authorize-controller.ts index 3d0baedd5..8e6fb1557 100644 --- a/src/components/authorize/authorize-controller.ts +++ b/src/components/authorize/authorize-controller.ts @@ -38,7 +38,7 @@ function createConsentCookie( res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { expires: consentCookieValue.expiry, secure: true, - httpOnly: true, + httpOnly: false, domain: res.locals.analyticsCookieDomain, }); } diff --git a/src/components/common/cookies/cookies-controller.ts b/src/components/common/cookies/cookies-controller.ts index 947e5f15c..d6a0803d0 100644 --- a/src/components/common/cookies/cookies-controller.ts +++ b/src/components/common/cookies/cookies-controller.ts @@ -42,7 +42,7 @@ function createConsentCookie( res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { expires: consentCookieValue.expiry, secure: true, - httpOnly: true, + httpOnly: false, domain: res.locals.analyticsCookieDomain, }); } From bd5d38b3a624578b28377e98602070a93314cf52 Mon Sep 17 00:00:00 2001 From: GTVJ Date: Fri, 26 Apr 2024 16:25:07 +0100 Subject: [PATCH 2/6] AUT-2733: Remove duplicated createConsentCookie function This function: 1. was duplicated in two controllers 2. serves only wrap the res.cookie(). I initially considered extracting this to be a more general purpose function but could see little value in this because it serves only to wrap the res.cookie() function provided by Express. --- .../authorize/authorize-controller.ts | 24 ++++++------------- .../common/cookies/cookies-controller.ts | 18 ++++---------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/components/authorize/authorize-controller.ts b/src/components/authorize/authorize-controller.ts index 8e6fb1557..281c682ac 100644 --- a/src/components/authorize/authorize-controller.ts +++ b/src/components/authorize/authorize-controller.ts @@ -8,10 +8,7 @@ import { import { getNextPathAndUpdateJourney, ERROR_CODES } from "../common/constants"; import { BadRequestError, QueryParamsError } from "../../utils/error"; import { ExpressRouteFunc } from "../../types"; -import { - CookieConsentModel, - CookieConsentServiceInterface, -} from "../common/cookie-consent/types"; +import { CookieConsentServiceInterface } from "../common/cookie-consent/types"; import { cookieConsentService } from "../common/cookie-consent/cookie-consent-service"; import { sanitize } from "../../utils/strings"; import { USER_JOURNEY_EVENTS } from "../common/state-machine/state-machine"; @@ -31,18 +28,6 @@ import { import { logger } from "../../utils/logger"; import { Claims } from "./claims-config"; -function createConsentCookie( - res: Response, - consentCookieValue: CookieConsentModel -) { - res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { - expires: consentCookieValue.expiry, - secure: true, - httpOnly: false, - domain: res.locals.analyticsCookieDomain, - }); -} - export function authorizeGet( authService: AuthorizeServiceInterface = authorizeService(), cookieService: CookieConsentServiceInterface = cookieConsentService(), @@ -166,7 +151,12 @@ export function authorizeGet( const consentCookieValue = cookieService.createConsentCookieValue(cookieConsent); - createConsentCookie(res, consentCookieValue); + res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { + expires: consentCookieValue.expiry, + secure: true, + httpOnly: false, + domain: res.locals.analyticsCookieDomain, + }); if ( startAuthResponse.data.user.gaCrossDomainTrackingId && diff --git a/src/components/common/cookies/cookies-controller.ts b/src/components/common/cookies/cookies-controller.ts index d6a0803d0..37791c8ea 100644 --- a/src/components/common/cookies/cookies-controller.ts +++ b/src/components/common/cookies/cookies-controller.ts @@ -5,7 +5,6 @@ import { COOKIES_PREFERENCES_SET, COOKIE_CONSENT, } from "../../../app.constants"; -import { CookieConsentModel } from "../cookie-consent/types"; const cookieService = cookieConsentService(); @@ -27,22 +26,15 @@ export function cookiesPost(req: Request, res: Response): void { consentValue === "true" ? COOKIE_CONSENT.ACCEPT : COOKIE_CONSENT.REJECT ); - createConsentCookie(res, consentCookieValue); - - res.locals.backUrl = req.body.originalReferer; - res.locals.analyticsConsent = consentValue === "true"; - res.locals.updated = true; - res.render("common/cookies/index.njk"); -} - -function createConsentCookie( - res: Response, - consentCookieValue: CookieConsentModel -) { res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { expires: consentCookieValue.expiry, secure: true, httpOnly: false, domain: res.locals.analyticsCookieDomain, }); + + res.locals.backUrl = req.body.originalReferer; + res.locals.analyticsConsent = consentValue === "true"; + res.locals.updated = true; + res.render("common/cookies/index.njk"); } From a982b937cff8f41513fd0ba742a465f67f79c1d4 Mon Sep 17 00:00:00 2001 From: GTVJ Date: Mon, 29 Apr 2024 14:01:28 +0100 Subject: [PATCH 3/6] AUT-2733: Encode `cookie_preferences_set` as String Updates call to res.cookie that set the cookie to use String encoding so that it matches the formatting used when the cookie is set client-side. --- src/components/authorize/authorize-controller.ts | 1 + src/components/common/cookies/cookies-controller.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/components/authorize/authorize-controller.ts b/src/components/authorize/authorize-controller.ts index 281c682ac..ea53322cf 100644 --- a/src/components/authorize/authorize-controller.ts +++ b/src/components/authorize/authorize-controller.ts @@ -156,6 +156,7 @@ export function authorizeGet( secure: true, httpOnly: false, domain: res.locals.analyticsCookieDomain, + encode: String, }); if ( diff --git a/src/components/common/cookies/cookies-controller.ts b/src/components/common/cookies/cookies-controller.ts index 37791c8ea..551af9c35 100644 --- a/src/components/common/cookies/cookies-controller.ts +++ b/src/components/common/cookies/cookies-controller.ts @@ -31,6 +31,7 @@ export function cookiesPost(req: Request, res: Response): void { secure: true, httpOnly: false, domain: res.locals.analyticsCookieDomain, + encode: String, }); res.locals.backUrl = req.body.originalReferer; From d47b96aee9039ad72ab00406be2f370b8268212b Mon Sep 17 00:00:00 2001 From: GTVJ Date: Tue, 30 Apr 2024 17:37:58 +0100 Subject: [PATCH 4/6] AUT-2733: Rename parameter passed to authorizeGet This reflects a suggestion made in the pull request to have the name more explicity reflect that it is a service relating to cookie consent. --- src/components/authorize/authorize-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/authorize/authorize-controller.ts b/src/components/authorize/authorize-controller.ts index ea53322cf..283c5887f 100644 --- a/src/components/authorize/authorize-controller.ts +++ b/src/components/authorize/authorize-controller.ts @@ -30,7 +30,7 @@ import { Claims } from "./claims-config"; export function authorizeGet( authService: AuthorizeServiceInterface = authorizeService(), - cookieService: CookieConsentServiceInterface = cookieConsentService(), + cookiesConsentService: CookieConsentServiceInterface = cookieConsentService(), kmsService: KmsDecryptionServiceInterface = new KmsDecryptionService(), jwtService: JwtServiceInterface = new JwtService() ): ExpressRouteFunc { @@ -149,7 +149,7 @@ export function authorizeGet( if (req.session.client.cookieConsentEnabled && cookieConsent) { const consentCookieValue = - cookieService.createConsentCookieValue(cookieConsent); + cookiesConsentService.createConsentCookieValue(cookieConsent); res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { expires: consentCookieValue.expiry, From dd3ac1e76d697dbfd65e9936cf3a3ed02f00d762 Mon Sep 17 00:00:00 2001 From: GTVJ Date: Wed, 1 May 2024 11:54:03 +0100 Subject: [PATCH 5/6] AUT-2733: Refactor and extend tests for calls to res.cookie Updates the tests to: 1. ensure that the call includes the expected arguments and flags (to ensure cookies are set with the HttpOnly and Secure flags and the expiry meets expectations). 2. separates these assertions from those that are unrelated 3. introduces a new helper for creating mock cookie consent services Co-authored-by: Andrew Moores <147620897+andrew-moores@users.noreply.github.com> --- .../tests/authorize-controller.test.ts | 69 ++++++++---- .../cookies/tests/cookies-controller.test.ts | 101 ++++++++++++++---- .../mock-cookie-consent-service-helper.ts | 19 ++++ 3 files changed, 149 insertions(+), 40 deletions(-) create mode 100644 test/helpers/mock-cookie-consent-service-helper.ts diff --git a/src/components/authorize/tests/authorize-controller.test.ts b/src/components/authorize/tests/authorize-controller.test.ts index da44351d1..ff279c30d 100644 --- a/src/components/authorize/tests/authorize-controller.test.ts +++ b/src/components/authorize/tests/authorize-controller.test.ts @@ -8,6 +8,7 @@ import { authorizeGet } from "../authorize-controller"; import { CookieConsentServiceInterface } from "../../common/cookie-consent/types"; import { COOKIE_CONSENT, + COOKIES_PREFERENCES_SET, OIDC_PROMPT, PATH_NAMES, } from "../../../app.constants"; @@ -22,6 +23,7 @@ import { createmockclaims } from "./test-data"; import { Claims } from "../claims-config"; import { getOrchToAuthExpectedClientId } from "../../../config"; import { createMockRequest } from "../../../../test/helpers/mock-request-helper"; +import { createMockCookieConsentService } from "../../../../test/helpers/mock-cookie-consent-service-helper"; describe("authorize controller", () => { let req: RequestOutput; @@ -55,11 +57,6 @@ describe("authorize controller", () => { success: true, }); - fakeCookieConsentService = { - getCookieConsent: sinon.fake(), - createConsentCookieValue: sinon.fake(), - }; - fakeKmsDecryptionService = { decrypt: sinon.fake.returns(Promise.resolve("jwt")), }; @@ -88,18 +85,24 @@ describe("authorize controller", () => { }); it("should redirect to /sign-in-or-create page with cookie preferences set", async () => { + req.body.cookie_preferences = "true"; + authServiceResponseData.data.user = { cookieConsent: COOKIE_CONSENT.ACCEPT, }; + fakeAuthorizeService = mockAuthService(authServiceResponseData); - const fakeCookieConsentService: CookieConsentServiceInterface = { - getCookieConsent: sinon.fake(), - createConsentCookieValue: sinon.fake.returns({ - value: JSON.stringify("cookieValue"), - expiry: "cookieExpires", - }), - } as unknown as CookieConsentServiceInterface; + const fakeCookieConsentService = createMockCookieConsentService( + req.body.cookie_preferences + ); + + const consentCookieValue = + fakeCookieConsentService.createConsentCookieValue( + req.body.cookie_preferences === "true" + ? COOKIE_CONSENT.ACCEPT + : COOKIE_CONSENT.REJECT + ); await authorizeGet( fakeAuthorizeService, @@ -108,7 +111,20 @@ describe("authorize controller", () => { fakeJwtService )(req as Request, res as Response); - expect(res.cookie).to.have.been.called; + expect(res.cookie).to.have.been.calledWith( + COOKIES_PREFERENCES_SET, + consentCookieValue.value, + sinon.match({ + expires: sinon.match((date: Date) => { + const expectedExpires = new Date(Date.now()); + expectedExpires.setFullYear(expectedExpires.getFullYear() + 1); + return Math.abs(date.getTime() - expectedExpires.getTime()) < 1000; + }), + secure: true, + httpOnly: false, + encode: String, + }) + ); expect(res.redirect).to.have.calledWith(PATH_NAMES.SIGN_IN_OR_CREATE); }); @@ -270,13 +286,16 @@ describe("authorize controller", () => { }; fakeAuthorizeService = mockAuthService(authServiceResponseData); - const fakeCookieConsentService: CookieConsentServiceInterface = { - getCookieConsent: sinon.fake(), - createConsentCookieValue: sinon.fake.returns({ - value: JSON.stringify("cookieValue"), - expiry: "cookieExpires", - }), - } as unknown as CookieConsentServiceInterface; + const fakeCookieConsentService = createMockCookieConsentService( + req.body.cookie_preferences + ); + + const consentCookieValue = + fakeCookieConsentService.createConsentCookieValue( + req.body.cookie_preferences === "true" + ? COOKIE_CONSENT.ACCEPT + : COOKIE_CONSENT.REJECT + ); await authorizeGet( fakeAuthorizeService, @@ -285,7 +304,15 @@ describe("authorize controller", () => { fakeJwtService )(req as Request, res as Response); - expect(res.cookie).to.have.been.called; + expect(res.cookie).to.have.been.calledWith( + COOKIES_PREFERENCES_SET, + consentCookieValue.value, + sinon.match({ + secure: true, + httpOnly: false, + encode: String, + }) + ); expect(res.redirect).to.have.calledWith( `${PATH_NAMES.SIGN_IN_OR_CREATE}?_ga=${gaTrackingId}` ); diff --git a/src/components/common/cookies/tests/cookies-controller.test.ts b/src/components/common/cookies/tests/cookies-controller.test.ts index 9e8c08ade..19ef0c56a 100644 --- a/src/components/common/cookies/tests/cookies-controller.test.ts +++ b/src/components/common/cookies/tests/cookies-controller.test.ts @@ -5,8 +5,13 @@ import { sinon } from "../../../../../test/utils/test-utils"; import { Request, Response } from "express"; import { cookiesGet, cookiesPost } from "../cookies-controller"; -import { COOKIES_PREFERENCES_SET, PATH_NAMES } from "../../../../app.constants"; +import { + COOKIE_CONSENT, + COOKIES_PREFERENCES_SET, + PATH_NAMES, +} from "../../../../app.constants"; import { mockResponse, RequestOutput, ResponseOutput } from "mock-req-res"; +import { createMockCookieConsentService } from "../../../../../test/helpers/mock-cookie-consent-service-helper"; import { createMockRequest } from "../../../../../test/helpers/mock-request-helper"; describe("cookies controller", () => { @@ -33,30 +38,88 @@ describe("cookies controller", () => { expect(res.locals.backUrl).to.equal("/last-page"); }); }); + describe("cookiesPost", () => { - it("should save analytics preferences as yes and render cookies page", () => { - req.body.cookie_preferences = "true"; - req.body.originalReferer = "/page-before-1"; + describe("where the user has consented to cookies", () => { + it("should call res.cookie with the expected arguments and flags", () => { + req.body.cookie_preferences = "true"; - cookiesPost(req as Request, res as Response); + const fakeCookieConsentService = createMockCookieConsentService( + req.body.cookie_preferences + ); - expect(res.render).to.have.been.calledWith("common/cookies/index.njk"); - expect(res.locals.analyticsConsent).to.equal(true); - expect(res.locals.updated).to.equal(true); - expect(res.locals.backUrl).to.equal("/page-before-1"); - expect(res.cookie).to.have.been.calledWith(COOKIES_PREFERENCES_SET); + const consentCookieValue = + fakeCookieConsentService.createConsentCookieValue( + req.body.cookie_preferences === "true" + ? COOKIE_CONSENT.ACCEPT + : COOKIE_CONSENT.REJECT + ); + + cookiesPost(req as Request, res as Response); + + expect(res.cookie).to.have.been.calledWith( + COOKIES_PREFERENCES_SET, + consentCookieValue.value, + sinon.match({ + secure: true, + httpOnly: false, + encode: String, + }) + ); + }); + + it("should render the page", () => { + req.body.cookie_preferences = "true"; + req.body.originalReferer = "/page-before-1"; + + cookiesPost(req as Request, res as Response); + + expect(res.render).to.have.been.calledWith("common/cookies/index.njk"); + expect(res.locals.analyticsConsent).to.equal(true); + expect(res.locals.updated).to.equal(true); + expect(res.locals.backUrl).to.equal("/page-before-1"); + }); }); - it("should save analytics preferences as no and render cookies page", () => { - req.body.cookie_preferences = "false"; - req.body.originalReferer = "/page-before-2"; - cookiesPost(req as Request, res as Response); + describe("where the user has not consented to cookies", () => { + it("should call res.cookie with the expected arguments and flags", () => { + req.body.cookie_preferences = "false"; - expect(res.render).to.have.been.calledWith("common/cookies/index.njk"); - expect(res.locals.analyticsConsent).to.equal(false); - expect(res.locals.updated).to.equal(true); - expect(res.locals.backUrl).to.equal("/page-before-2"); - expect(res.cookie).to.have.been.calledWith(COOKIES_PREFERENCES_SET); + const fakeCookieConsentService = createMockCookieConsentService( + req.body.cookie_preferences + ); + + const consentCookieValue = + fakeCookieConsentService.createConsentCookieValue( + req.body.cookie_preferences === "true" + ? COOKIE_CONSENT.ACCEPT + : COOKIE_CONSENT.REJECT + ); + + cookiesPost(req as Request, res as Response); + + expect(res.cookie).to.have.been.calledWith( + COOKIES_PREFERENCES_SET, + consentCookieValue.value, + sinon.match({ + secure: true, + httpOnly: false, + encode: String, + }) + ); + }); + + it("should render the page", () => { + req.body.cookie_preferences = "false"; + req.body.originalReferer = "/page-before-2"; + + cookiesPost(req as Request, res as Response); + + expect(res.render).to.have.been.calledWith("common/cookies/index.njk"); + expect(res.locals.analyticsConsent).to.equal(false); + expect(res.locals.updated).to.equal(true); + expect(res.locals.backUrl).to.equal("/page-before-2"); + }); }); }); }); diff --git a/test/helpers/mock-cookie-consent-service-helper.ts b/test/helpers/mock-cookie-consent-service-helper.ts new file mode 100644 index 000000000..e9802bb6f --- /dev/null +++ b/test/helpers/mock-cookie-consent-service-helper.ts @@ -0,0 +1,19 @@ +import { sinon } from "../utils/test-utils"; +import { CookieConsentServiceInterface } from "../../src/components/common/cookie-consent/types"; + +export function createMockCookieConsentService( + userCookieConsentPreference: string +): CookieConsentServiceInterface { + const expiryDate: Date = new Date(); + expiryDate.setFullYear(expiryDate.getFullYear() + 1); + + return { + getCookieConsent: sinon.fake(), + createConsentCookieValue: sinon.fake.returns({ + value: JSON.stringify({ + analytics: userCookieConsentPreference === "true", + }), + expiry: expiryDate, + }), + }; +} From 08b580509c67fbe91e20b96a69528f2ef112c9d8 Mon Sep 17 00:00:00 2001 From: GTVJ Date: Thu, 2 May 2024 15:16:20 +0100 Subject: [PATCH 6/6] AUT-2733: Update CookieConsentModel to reflect Express Suggestion on PR #1588 was that CookieConsentModel should reflect the naming used in Express req.cookie (i.e. to use 'expires' rather than 'expiry'. See comment https://github.com/govuk-one-login/authentication-frontend/pull/1588#discussion_r1587274320 --- src/components/authorize/authorize-controller.ts | 2 +- .../common/cookie-consent/cookie-consent-service.ts | 2 +- .../cookie-consent/tests/cookie-consent-service.test.ts | 6 +++--- src/components/common/cookie-consent/types.ts | 2 +- src/components/common/cookies/cookies-controller.ts | 2 +- test/helpers/mock-cookie-consent-service-helper.ts | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/authorize/authorize-controller.ts b/src/components/authorize/authorize-controller.ts index 283c5887f..42e41986f 100644 --- a/src/components/authorize/authorize-controller.ts +++ b/src/components/authorize/authorize-controller.ts @@ -152,7 +152,7 @@ export function authorizeGet( cookiesConsentService.createConsentCookieValue(cookieConsent); res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { - expires: consentCookieValue.expiry, + expires: consentCookieValue.expires, secure: true, httpOnly: false, domain: res.locals.analyticsCookieDomain, diff --git a/src/components/common/cookie-consent/cookie-consent-service.ts b/src/components/common/cookie-consent/cookie-consent-service.ts index 222bec6b0..7801a074f 100644 --- a/src/components/common/cookie-consent/cookie-consent-service.ts +++ b/src/components/common/cookie-consent/cookie-consent-service.ts @@ -39,7 +39,7 @@ export function cookieConsentService(): CookieConsentServiceInterface { cookieExpires.setFullYear(cookieExpires.getFullYear() - 1); } - return { value: JSON.stringify(cookieValue), expiry: cookieExpires }; + return { value: JSON.stringify(cookieValue), expires: cookieExpires }; }; return { diff --git a/src/components/common/cookie-consent/tests/cookie-consent-service.test.ts b/src/components/common/cookie-consent/tests/cookie-consent-service.test.ts index 93130c7f4..cb516459f 100644 --- a/src/components/common/cookie-consent/tests/cookie-consent-service.test.ts +++ b/src/components/common/cookie-consent/tests/cookie-consent-service.test.ts @@ -36,7 +36,7 @@ describe("cookie consent service", () => { COOKIE_CONSENT.NOT_ENGAGED ); expect(result.value).to.have.be.equal("{}"); - expect(result.expiry.getFullYear()).to.have.be.equal( + expect(result.expires.getFullYear()).to.have.be.equal( new Date().getFullYear() - 1 ); }); @@ -46,7 +46,7 @@ describe("cookie consent service", () => { COOKIE_CONSENT.ACCEPT ); expect(result.value).to.have.be.equal('{"analytics":true}'); - expect(result.expiry.getFullYear()).to.have.be.equal( + expect(result.expires.getFullYear()).to.have.be.equal( new Date().getFullYear() + 1 ); }); @@ -56,7 +56,7 @@ describe("cookie consent service", () => { COOKIE_CONSENT.REJECT ); expect(result.value).to.have.be.equal('{"analytics":false}'); - expect(result.expiry.getFullYear()).to.have.be.equal( + expect(result.expires.getFullYear()).to.have.be.equal( new Date().getFullYear() + 1 ); }); diff --git a/src/components/common/cookie-consent/types.ts b/src/components/common/cookie-consent/types.ts index a9460cbc1..763b99c3f 100644 --- a/src/components/common/cookie-consent/types.ts +++ b/src/components/common/cookie-consent/types.ts @@ -5,5 +5,5 @@ export interface CookieConsentServiceInterface { export interface CookieConsentModel { value: string; - expiry: Date; + expires: Date; } diff --git a/src/components/common/cookies/cookies-controller.ts b/src/components/common/cookies/cookies-controller.ts index 551af9c35..c3ffd0054 100644 --- a/src/components/common/cookies/cookies-controller.ts +++ b/src/components/common/cookies/cookies-controller.ts @@ -27,7 +27,7 @@ export function cookiesPost(req: Request, res: Response): void { ); res.cookie(COOKIES_PREFERENCES_SET, consentCookieValue.value, { - expires: consentCookieValue.expiry, + expires: consentCookieValue.expires, secure: true, httpOnly: false, domain: res.locals.analyticsCookieDomain, diff --git a/test/helpers/mock-cookie-consent-service-helper.ts b/test/helpers/mock-cookie-consent-service-helper.ts index e9802bb6f..ce1deb749 100644 --- a/test/helpers/mock-cookie-consent-service-helper.ts +++ b/test/helpers/mock-cookie-consent-service-helper.ts @@ -13,7 +13,7 @@ export function createMockCookieConsentService( value: JSON.stringify({ analytics: userCookieConsentPreference === "true", }), - expiry: expiryDate, + expires: expiryDate, }), }; }