From f48f5c89b8c47337ecfa09df218101db73fd35d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dafydd=20Ll=C5=B7r=20Pearson?= Date: Thu, 14 Dec 2023 13:17:38 +0000 Subject: [PATCH 1/5] chore: Don't error on unused vars in Editor [skip pizza] (#2567) --- editor.planx.uk/.eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor.planx.uk/.eslintrc b/editor.planx.uk/.eslintrc index d0141dc994..56e7548930 100644 --- a/editor.planx.uk/.eslintrc +++ b/editor.planx.uk/.eslintrc @@ -55,7 +55,7 @@ } ], "@typescript-eslint/no-unused-vars": [ - "error", + "warn", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" From 706ba87ae104611c616d8413baac5dd3e0aa7696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dafydd=20Ll=C5=B7r=20Pearson?= Date: Fri, 15 Dec 2023 12:34:31 +0000 Subject: [PATCH 2/5] fix: Set X-Content-Type-Options headers on Cloudfront (#2569) --- infrastructure/application/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/infrastructure/application/index.ts b/infrastructure/application/index.ts index e05577573e..ae7e1d2aed 100644 --- a/infrastructure/application/index.ts +++ b/infrastructure/application/index.ts @@ -680,6 +680,10 @@ export = async () => { includeSubdomains: true, preload: true, }, + // Set X-Content-Type-Options = "nosniff" + contentTypeOptions: { + override: true, + }, }, } ).id, From 0864da6b08b72c7e63bd5b80d2911684242faf42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dafydd=20Ll=C5=B7r=20Pearson?= Date: Fri, 15 Dec 2023 13:18:43 +0000 Subject: [PATCH 3/5] fix: Set httpOnly attribute on JWT cookie (#2570) --- api.planx.uk/modules/auth/controller.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/api.planx.uk/modules/auth/controller.ts b/api.planx.uk/modules/auth/controller.ts index 69ac070316..7f8088a2de 100644 --- a/api.planx.uk/modules/auth/controller.ts +++ b/api.planx.uk/modules/auth/controller.ts @@ -53,6 +53,7 @@ export const handleSuccess = (req: Request, res: Response) => { if (isLiveEnv()) { cookie.secure = true; cookie.sameSite = "none"; + cookie.httpOnly = true; } res.cookie("jwt", req.user.jwt, cookie); From cf8a6abb86f988999576d2135dd4966c4ee80a2d Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Fri, 15 Dec 2023 13:52:37 +0000 Subject: [PATCH 4/5] fix: decode organisation details from `access_token` for Uniform authentication (#2571) --- api.planx.uk/modules/send/uniform/uniform.ts | 23 ++++++++++--------- .../src/invite-to-pay/mocks/server-mocks.yaml | 8 +++---- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/api.planx.uk/modules/send/uniform/uniform.ts b/api.planx.uk/modules/send/uniform/uniform.ts index 8bc552e053..ce8e6b2dda 100644 --- a/api.planx.uk/modules/send/uniform/uniform.ts +++ b/api.planx.uk/modules/send/uniform/uniform.ts @@ -1,11 +1,12 @@ import axios, { AxiosRequestConfig, isAxiosError } from "axios"; import { NextFunction, Request, Response } from "express"; -import { Buffer } from "node:buffer"; import FormData from "form-data"; import fs from "fs"; -import { markSessionAsSubmitted } from "../../saveAndReturn/service/utils"; import { gql } from "graphql-request"; +import jwt from "jsonwebtoken"; +import { Buffer } from "node:buffer"; import { $api } from "../../../client"; +import { markSessionAsSubmitted } from "../../saveAndReturn/service/utils"; import { buildSubmissionExportZip } from "../utils/exportZip"; interface UniformClient { @@ -21,8 +22,6 @@ interface UniformSubmissionResponse { interface RawUniformAuthResponse { access_token: string; - "organisation-name": string; - "organisation-id": string; } interface UniformAuthResponse { @@ -204,19 +203,21 @@ async function authenticate({ throw Error("Failed to authenticate to Uniform - no access token returned"); } - if ( - !response.data["organisation-name"] || - !response.data["organisation-id"] - ) { + // Decode access_token to get "organisation-name" & "organisation-id" + const decodedAccessToken = jwt.decode(response.data.access_token) as any; + const organisation = decodedAccessToken?.["organisation-name"]; + const organisationId = decodedAccessToken?.["organisation-id"]; + + if (!organisation || !organisationId) { throw Error( - "Failed to authenticate to Uniform - no organisation details returned", + "Failed to authenticate to Uniform - failed to decode organisation details from access_token", ); } const uniformAuthResponse: UniformAuthResponse = { token: response.data.access_token, - organisation: response.data["organisation-name"], - organisationId: response.data["organisation-id"], + organisation: organisation, + organisationId: organisationId, }; return uniformAuthResponse; diff --git a/e2e/tests/api-driven/src/invite-to-pay/mocks/server-mocks.yaml b/e2e/tests/api-driven/src/invite-to-pay/mocks/server-mocks.yaml index a1419013a9..65892e19ed 100644 --- a/e2e/tests/api-driven/src/invite-to-pay/mocks/server-mocks.yaml +++ b/e2e/tests/api-driven/src/invite-to-pay/mocks/server-mocks.yaml @@ -11,7 +11,7 @@ "messsage": "MOCKED RESPONSE" } -# UNIFORM token generation +# UNIFORM token generation, access_token is mock JWT with "organisation-name" & "organisation-id" properties - request: method: POST path: / @@ -21,9 +21,9 @@ Content-Type: application/json body: > { - "access_token": "TEST_TOKEN", - "organisation-name": "MOCKED", - "organisation-id": "MOCKED" + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdhbmlzYXRpb24tbmFtZSI6Ik1PQ0tFRCIsIm9yZ2FuaXNhdGlvbi1pZCI6Ik1PQ0tFRCJ9.p0DE8MUc9obE751XWOYPQWWtLXtq8-kJMPre4VuOBHg", + "token_type": "Bearer", + "expires_in": 35999 } # UNIFORM submissions From 0e1ca28a32ae69a962f6b57b571a0916a26b5f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dafydd=20Ll=C5=B7r=20Pearson?= Date: Fri, 15 Dec 2023 14:03:42 +0000 Subject: [PATCH 5/5] Revert "fix: Set httpOnly attribute on JWT cookie (#2570)" (#2572) This reverts commit 0864da6b08b72c7e63bd5b80d2911684242faf42. --- api.planx.uk/modules/auth/controller.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/api.planx.uk/modules/auth/controller.ts b/api.planx.uk/modules/auth/controller.ts index 7f8088a2de..69ac070316 100644 --- a/api.planx.uk/modules/auth/controller.ts +++ b/api.planx.uk/modules/auth/controller.ts @@ -53,7 +53,6 @@ export const handleSuccess = (req: Request, res: Response) => { if (isLiveEnv()) { cookie.secure = true; cookie.sameSite = "none"; - cookie.httpOnly = true; } res.cookie("jwt", req.user.jwt, cookie);