Security for web applications in node
This library provides a Express middleware Request Handler which will protect
an application from Cross Site Request Forgery (CSRF) attacks. The middleware
works by looking for a token within the request which should match a token held
within the CHS session. The middleware will expect all requests from methods
which modify data (for example POST
/DELETE
/PUT
) to include the CSRF
token. This implements a
Synchronisation Token Pattern approach
-
Install the library (if not already installed).
npm i @companieshouse/web-security-node@^3.2.0
-
Define the options for the middleware and add the middleware to the application
import { CsrfProtectionMiddleware } from " @companieshouse/web-security-node" import { SessionStore, SessionMiddleware } from '@companieshouse/node-session-handler'; import express from "express"; import cookieParser from 'cookie-parser'; import Redis from 'ioredis'; const app = express(); // apply other middlewares app.use(cookieParser()); app.use(express.urlencoded({ extended: true })); const cookieName = '__SID' const cookieConfig = { cookieName, cookieSecret: config.COOKIE_SECRET, cookieDomain: config.COOKIE_DOMAIN, cookieTimeToLiveInSeconds: parseInt(config.DEFAULT_SESSION_EXPIRATION, 10) }; const sessionStore = new SessionStore(new Redis(`redis://${config.CACHE_SERVER}`)); // Important the session Middleware is required before this middleware since the // token is stored within the session app.use(SessionMiddleware(cookieConfig, sessionStore)); const csrfMiddlewareOptions = { sessionStore, enabled: true, sessionCookieName: cookieName } app.use(createLoggerMiddleware(config.applicationNamespace)); // It is important that CSRF Protection follows the Sesion and urlencoded // Middlewares, maybe put at end of the middleware chain (before // controllers) app.use(CsrfProtectionMiddleware(csrfMiddlewareOptions)) app.use(helmet());
-
Amend the Nunjucks configuration to add the thirdparty templates from this library:
nunjucks .configure([ "dist/views", "node_modules/govuk-frontend/", "node_modules/govuk-frontend/components/", "node_modules/@companies-house/" ], nunjucksConfig)
-
In each form which submits data (or modifies data) add the following macro call
{% from "web-security-node/components/csrf-token-input/macro.njk" import csrfTokenInput %} <form action="POST"> {{ csrfTokenInput({ csrfToken: csrfToken }) }} <!-- Other form items ommitted --> </form>
Provides configuration to the middleware.
-
enabled
(boolean required) - whether or not to apply CSRF protections -
sessionStore
(SessionStore required) - a SessionStore instance to manage the CHS session -
sessionCookieName
(string) - name of the cookie storing the signed Session ID -
csrfTokenFactory
(supplier of string) - a callable when called will return a string to use as the session's CSRF token. Has signature:() => string
Defaults to a uuid supplier if not supplied.
-
createWhenCsrfTokenAbsent
(boolean) - whether to generate a new CSRF token if not present in the session. Only run on non-mutable requests (e.g. GET) -
headerName
(string) - name of the header to check. Defaults toX-CSRF-TOKEN
-
parameterName
(string) - name of the parameter in the request body to check. Defaults to_csrf
.
A Request Handler capable of being used as a express Middleware function. Its
responsibility is checking that all mutable requests include a csrf token which
indicates that they originated from the same CHS session and not an CSRF
attempt. The middleware expects that all mutable requests contain a token which
matches a token stored within the CHS session. It will add csrfToken
to
locals so that views can reference it as a variable.
options
- (CsrfOptions required) - the configuration for the middleware is provided as an object which implements the interfaceCsrfOptions
This function is the default CSRF issuing function, it essentially provides an uuid.
CsrfTokensMismatchError
- Thrown when the CSRF token is either missing
in the mutable request or does not match the CSRF token within the CHS session.
MissingCsrfSessionToken
- Thrown when there is no CSRF token within the
session to match the request's Token against.