npm package: @lightspeed/express-csp-middleware
Description: Common content security policy headers Express middleware for Lightspeed apps
Latest version: 1.0.2

# `@lightspeed/express-csp-middleware`

[![npm version](https://badge.fury.io/js/%40lightspeed%2Fexpress-csp-middleware.svg)](https://badge.fury.io/js/%40lightspeed%2Fexpress-csp-middleware)

## Introduction

[**Express**](https://expressjs.com/) middleware for generating the HTTP [`Content-Security-Policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) header for Lightspeed apps, allowing developers to control resources the user agent is allowed to load for a given page.

## Quick Start

1. Install the dependency in your webapp.

```sh
yarn add @lightspeed/express-csp-middleware
```

2. Apply the middleware to your Express server.

```ts
// server.ts
import express from 'express';
import { cspMiddleware } from '@lightspeed/express-csp-middleware';

const app = express();
app.use(cspMiddleware({ env: process.env.NODE_CONFIG_ENV }));
```

3. Script tags from HTML returned from the server must be attributed with the same unique `nonce` for the given request. For example, in a `Next.js` app with serverside rendering, apply the nonce as follows:

```tsx
// app/_document.tsx
import React from 'react';
import Document, { Head, Main, NextScript, NextDocumentContext } from 'next/document';

type MyDocumentProps = {
  nonce: string;
};

export default class MyDocument extends Document<MyDocumentProps> {
  static async getInitialProps(ctx: NextDocumentContext) {
    const { nonce } = (ctx.res as any).locals;
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps, nonce };
  }

  render() {
    return (
      <html>
        <Head nonce={this.props.nonce}>
          <title>Lightspeed Retail - Cool Page</title>
        </Head>
        <body>
          <Main />
          <NextScript nonce={this.props.nonce} />
        </body>
      </html>
    );
  }
}
```

4. Update all pages to include a `getInitialProps` method on the component. This will override nextjs to force server-side rendering and provide access to `req` and `res` in `_document`. You can read more [here](https://github.com/zeit/next.js/issues/7791#issuecomment-509334319)

```tsx
// pages/index.tsx
import * as React from 'react';

const Hello = () => {
  return <div>Hello World!</div>;
};

Hello.getInitialProps = async () => ({});
```

### Customizing your own presets

It is possible to customize the CSP middleware policies.

You may pass in an object into the `additionalPresets` keys. These values will either replace the existing presets or create a new entity.

In order for them to be configured properly, please ensure that the key's match and that the value is an array of strings.

The default values used by the CSP middleware are exported to faciliate extending the defaults rather than replacing them.

```ts
import { cspMiddleware, imgSrc } from '@lightspeed/express-csp-middleware';

const myExtraPresets = {
  'img-src': imgSrc.concat(['"cdn-a"', '"cdn-b"']),
  'connect-src': ['"http:"'],
};

app.use(cspMiddleware({ env: process.env.NODE_CONFIG_ENV, additionalPresets: myExtraPresets }));
```