diff --git a/api.planx.uk/modules/ordnanceSurvey/middleware.ts b/api.planx.uk/modules/ordnanceSurvey/middleware.ts deleted file mode 100644 index 973387cf31..0000000000 --- a/api.planx.uk/modules/ordnanceSurvey/middleware.ts +++ /dev/null @@ -1,40 +0,0 @@ -import cors, { CorsOptions } from "cors"; -import { RequestHandler } from "express"; -import { ServerError } from "../../errors"; - -const MAP_ALLOWLIST: RegExp[] = [ - // Local development - /^http:\/\/(127\.0\.0\.1|localhost):(3000|5173|6006|7007)$/i, - // Documentation - /^https:\/\/.*\.netlify\.app$/i, - // PlanX - /^https:\/\/.*planx\.(pizza|dev|uk)$/i, - // Custom domains - /^https:\/\/.*(\.gov\.uk)$/i, -]; - -const checkAllowedOrigins: CorsOptions["origin"] = (origin, callback) => { - const isAllowed = - origin && MAP_ALLOWLIST.some((pattern) => pattern.test(origin)); - - !origin || isAllowed - ? callback(null, true) - : callback(new ServerError({ status: 401, message: "Unauthorised" })); -}; - -/** - * Overwrite CORS options for OS Proxy endpoint - * This endpoint is accessed from different origins to the rest of the API - */ -export const osProxyCORS: RequestHandler = cors({ - credentials: true, - methods: "*", - origin: checkAllowedOrigins, - allowedHeaders: [ - "Accept", - "Authorization", - "Content-Type", - "Origin", - "X-Requested-With", - ], -}); diff --git a/api.planx.uk/modules/ordnanceSurvey/ordnanceSurvey.test.ts b/api.planx.uk/modules/ordnanceSurvey/ordnanceSurvey.test.ts index 967cdc240a..56e38d548c 100644 --- a/api.planx.uk/modules/ordnanceSurvey/ordnanceSurvey.test.ts +++ b/api.planx.uk/modules/ordnanceSurvey/ordnanceSurvey.test.ts @@ -17,7 +17,6 @@ describe("Ordnance Survey proxy endpoint", () => { .reply(200, { test: "returned tile" }); await get(ENDPOINT + TILE_PATH) - .set({ origin: "https://123.planx.pizza" }) .expect(200) .then((response) => { expect(response.body).toEqual({ @@ -33,7 +32,6 @@ describe("Ordnance Survey proxy endpoint", () => { .reply(200, { test: "returned tile" }); await get(ENDPOINT + TILE_PATH + "?srs=3857") - .set({ origin: "https://www.planx.dev" }) .expect(200) .then((response) => { expect(response.body).toEqual({ @@ -49,7 +47,6 @@ describe("Ordnance Survey proxy endpoint", () => { .reply(401, { test: "failed request" }); await get(ENDPOINT + TILE_PATH) - .set({ origin: "https://www.planx.uk" }) .expect(401) .then((response) => { expect(response.body).toEqual({ @@ -57,76 +54,6 @@ describe("Ordnance Survey proxy endpoint", () => { }); }); }); - - describe("CORS functionality", () => { - it("blocks requests which are not from a valid referrer", async () => { - await get(ENDPOINT + TILE_PATH) - .set({ origin: "https://www.invalid-site.com" }) - .expect(401) - .then((response) => { - expect(response.body).toEqual({ - error: "Unauthorised", - }); - }); - }); - - it("allows requests from allow-listed URLs", async () => { - nock(OS_DOMAIN) - .get(TILE_PATH) - .query({ key: process.env.ORDNANCE_SURVEY_API_KEY }) - .reply(200, { test: "returned tile" }); - - await get(ENDPOINT + TILE_PATH) - .set({ origin: "https://oslmap.netlify.app" }) - .expect(200) - .then((response) => { - expect(response.body).toEqual({ - test: "returned tile", - }); - expect(response.headers["cross-origin-resource-policy"]).toEqual( - "cross-origin", - ); - }); - }); - - it("allows requests from PlanX", async () => { - nock(OS_DOMAIN) - .get(TILE_PATH) - .query({ key: process.env.ORDNANCE_SURVEY_API_KEY }) - .reply(200, { test: "returned tile" }); - - await get(ENDPOINT + TILE_PATH) - .set({ origin: "https://www.planx.dev" }) - .expect(200) - .then((response) => { - expect(response.body).toEqual({ - test: "returned tile", - }); - expect(response.headers["cross-origin-resource-policy"]).toEqual( - "cross-origin", - ); - }); - }); - - it("allows requests from custom domains", async () => { - nock(OS_DOMAIN) - .get(TILE_PATH) - .query({ key: process.env.ORDNANCE_SURVEY_API_KEY }) - .reply(200, { test: "returned tile" }); - - await get(ENDPOINT + TILE_PATH) - .set({ origin: "https://planningservices.buckinghamshire.gov.uk" }) - .expect(200) - .then((response) => { - expect(response.body).toEqual({ - test: "returned tile", - }); - expect(response.headers["cross-origin-resource-policy"]).toEqual( - "cross-origin", - ); - }); - }); - }); }); describe("appendAPIKey helper function", () => { diff --git a/api.planx.uk/modules/ordnanceSurvey/routes.ts b/api.planx.uk/modules/ordnanceSurvey/routes.ts index 1d1f88489d..b8f5204c94 100644 --- a/api.planx.uk/modules/ordnanceSurvey/routes.ts +++ b/api.planx.uk/modules/ordnanceSurvey/routes.ts @@ -1,9 +1,8 @@ import { Router } from "express"; import { useOrdnanceSurveyProxy } from "./controller"; -import { osProxyCORS } from "./middleware"; const router = Router(); -router.use("/proxy/ordnance-survey", osProxyCORS, useOrdnanceSurveyProxy); +router.use("/proxy/ordnance-survey", useOrdnanceSurveyProxy); export default router; diff --git a/api.planx.uk/server.ts b/api.planx.uk/server.ts index 8c95c29f04..189a698cb8 100644 --- a/api.planx.uk/server.ts +++ b/api.planx.uk/server.ts @@ -39,12 +39,23 @@ useSwaggerDocs(app); app.set("trust proxy", 1); const checkAllowedOrigins: CorsOptions["origin"] = (origin, callback) => { + if (!origin) return callback(null, true); + const isTest = process.env.NODE_ENV === "test"; - const isDevelopment = process.env.APP_ENVIRONMENT === "development"; + const localDevEnvs = + /^http:\/\/(127\.0\.0\.1|localhost):(3000|5173|6006|7007)\/$/; + const isDevelopment = + process.env.APP_ENVIRONMENT === "development" || localDevEnvs.test(origin); const allowList = process.env.CORS_ALLOWLIST?.split(", ") || []; - const isAllowed = Boolean(origin && allowList.includes(origin)); + const isAllowed = Boolean(allowList.includes(origin)); + const isMapDocs = Boolean(origin.endsWith("oslmap.netlify.app")); + + console.log("*******************"); + console.log({ origin }); + console.log({ isMapDocs }); + console.log("*******************"); - !origin || isTest || isDevelopment || isAllowed + isTest || isDevelopment || isAllowed || isMapDocs ? callback(null, true) : callback(new Error("Not allowed by CORS")); };