diff --git a/packages/api/src/lib/middleware/embeddableResourceSecurityHeaders.ts b/packages/api/src/lib/middleware/embeddableResourceSecurityHeaders.ts new file mode 100644 index 0000000..a08007a --- /dev/null +++ b/packages/api/src/lib/middleware/embeddableResourceSecurityHeaders.ts @@ -0,0 +1,22 @@ +import type { Options } from '@middy/http-security-headers'; + +/** + * Overrides for `@middy/http-security-headers` so responses can be embedded + * cross-origin (e.g. ``). + * + * Middy's defaults include `Cross-Origin-Resource-Policy: same-origin` and + * `Cross-Origin-Embedder-Policy: require-corp`, which cause browsers to block + * those embeds when the app runs on another origin. + * + * Pass this as `securityHeadersOptions` in `middyfy()` for handlers that serve + * resources embedded by other sites. + */ +export const embeddableResourceSecurityHeaders: SecurityHeadersOptions = { + crossOriginResourcePolicy: { policy: 'cross-origin' }, + crossOriginEmbedderPolicy: false, + crossOriginOpenerPolicy: false, +}; + +export type SecurityHeadersOptions = { + [K in keyof Options]?: Options[K] | false; +}; diff --git a/packages/api/src/lib/middleware/index.ts b/packages/api/src/lib/middleware/index.ts index 113c0b8..2a3dea1 100644 --- a/packages/api/src/lib/middleware/index.ts +++ b/packages/api/src/lib/middleware/index.ts @@ -1,2 +1,3 @@ export { default as httpErrorHandler } from './httpErrorHandlerMiddleware'; +export * from './embeddableResourceSecurityHeaders'; export * from './middyfy'; diff --git a/packages/api/src/lib/middleware/middyfy.ts b/packages/api/src/lib/middleware/middyfy.ts index 4a39f9e..21a69e0 100644 --- a/packages/api/src/lib/middleware/middyfy.ts +++ b/packages/api/src/lib/middleware/middyfy.ts @@ -3,6 +3,7 @@ import doNotWaitForEmptyEventLoop from '@middy/do-not-wait-for-empty-event-loop' import cors from '@middy/http-cors'; import middyJsonBodyParser from '@middy/http-json-body-parser'; import httpSecurityHeaders from '@middy/http-security-headers'; +import type { SecurityHeadersOptions } from './embeddableResourceSecurityHeaders'; import validator from '@middy/validator'; import Ajv, { type Options as AjvOptions, type ValidateFunction } from 'ajv'; import addFormats from 'ajv-formats'; @@ -27,6 +28,7 @@ type MiddyfyProps = { outputSchema?: Record; ajvOptions?: AjvOptions; corsOptions?: Record | false; + securityHeadersOptions?: SecurityHeadersOptions; }; const ajvDefaultOptions: AjvOptions = { @@ -141,6 +143,7 @@ export const middyfy = ({ outputSchema, ajvOptions, corsOptions, + securityHeadersOptions, }: MiddyfyProps) => { let inputSchema; if (bodySchema || querySchema) { @@ -183,7 +186,9 @@ export const middyfy = ({ ); } - middyfiedHandler = middyfiedHandler.use(httpSecurityHeaders()); + middyfiedHandler = middyfiedHandler.use( + httpSecurityHeaders(securityHeadersOptions), + ); if (corsOptions !== false) { middyfiedHandler = middyfiedHandler.use(