Maria
Maria

Reputation: 31

How to add HTTP security headers to Next.js app

I am completely new in web development and I'm trying to add HTTP security headers to my Next.js app but if I check it in securityheader.com it doesn't seem to work.

const express = require("express");
const next = require("next");
const helmet = require("helmet");

const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

app
  .prepare()
  .then(() => {
    const server = express();
    server.use(helmet());
    server.use(helmet.xframe());
    server.use(helmet.hsts());

    server.get("*", (req, res) => {
      return handle(req, res);
    });

    server.listen(3000, err => {
      if (err) throw err;
      console.log("> Ready on http://localhost:3000");
    });
  })
  .catch(ex => {
    console.error(ex.stack);
    process.exit(1);
  });

I'm looking for information for 4 days already and I still didn't find any example how to do it and I can't figure it out what exactly I'm doing wrong.

Upvotes: 3

Views: 6916

Answers (2)

Fedor Parfenov
Fedor Parfenov

Reputation: 46

I found 2 solutions:

  1. You can use Jaga Apple's next-secure-headers npm package which can be found here on GitHub. This is basically a TypeScript-based wrapper that can be used on the whole App component or on individual Page components, by accessing a request object during the Next.js getInitialProps lifecycle, which unfortunately also forms this issue. You will also need to know a little bit of TypeScript to use it, as well as having to install TypeScript according to these Next.js instructions, or this Next.js tutorial.
  2. The above solution, however, currently does not work if you are deploying your Next.js project to Vercel (which used to be Zeit/Now), which is what I personally prefer since Next.js was created for Vercel. The solution I found for this case was to implement a custom routes/headers configuration in now.json, for example:
{
  ..., // <-- Other configuration options
  "routes": [
    {
      "src": "/.*",
      "headers": {
        "Content-Security-Policy": "default-src 'self'; img-src 'self' https://cdn.sanity.io; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'",
        "Feature-Policy": "'none'",
        "Referrer-Policy": "same-origin",
        "X-Content-Type-Options": "nosniff",
        "X-Frame-Options": "deny",
        "X-XSS-Protection": "1"
      },
      "continue": true
    }
  ]
}

Upvotes: 2

felixmosh
felixmosh

Reputation: 35593

Content-Security-Policy is not enabled by default in helmet, to enable it use

server.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    styleSrc: ["'self'", 'maxcdn.bootstrapcdn.com']
  }
}))

to enable X-Frame-Options

server.use(frameguard({
  action: 'allow-from',
  domain: 'http://example.com'
}))

For more info, check lib docs

Upvotes: 0

Related Questions