Skip to content

Instantly share code, notes, and snippets.

@unicornware
Created January 15, 2022 05:51
Show Gist options
  • Save unicornware/9434d6185f3cc95ada7c9504fdccbb4c to your computer and use it in GitHub Desktop.
Save unicornware/9434d6185f3cc95ada7c9504fdccbb4c to your computer and use it in GitHub Desktop.
NestJS - CsurfMiddleware
import { OrUndefined } from '@flex-development/tutils'
import { Injectable, NestMiddleware } from '@nestjs/common'
import { ENV } from '@sneusers/config/configuration'
import csurf, { CookieOptions } from 'csurf'
import { NextFunction, Request, Response } from 'express'
/**
* @file Middleware - CsurfMiddleware
* @module middleware/CsurfMiddleware
* @see https://github.com/expressjs/csurf
*/
@Injectable()
export default class CsurfMiddleware implements NestMiddleware {
/**
* @static
* @readonly
* @property {CsurfOptions} options - `csurf` options
*/
static readonly options: CsurfOptions
/**
* Sets configuration options.
*
* @see https://github.com/expressjs/csurf#options
*
* @param {CsurfOptions} [options={}] - Configuration options
* @return {typeof CsurfMiddleware} Update middleware class
*/
static configure(options: CsurfOptions = {}): typeof CsurfMiddleware {
return Object.assign(this, {
options: { ...options, cookie: CsurfMiddleware.cookie(options.cookie) }
})
}
/**
* Merge instance cookie options with default cookie options.
*
* @see https://github.com/expressjs/csurf#cookie
*
* @param {CookieOptions | boolean} [cookie=true] - csurf cookie options
* @return {CookieOptions} Merged options
*/
static cookie(cookie: CsurfOptions['cookie'] = true): CookieOptions {
const COOKIE_DEFAULTS: CookieOptions = {
domain: ENV.HOST,
expires: new Date(Date.now() + Number.parseInt(ENV.JWT_EXP_ACCESS)),
httpOnly: true,
sameSite: 'strict',
secure: ENV.PROD
}
if (typeof cookie === 'object') return { ...COOKIE_DEFAULTS, ...cookie }
return COOKIE_DEFAULTS
}
/**
* Extracts a csurf token from an incoming request header.
*
* @param {Request} req - Incoming request
* @return {OrUndefined<string>} Extracted token
*/
static extract(req: Request): OrUndefined<string> {
const route = ENV.TEST ? req.path : req.baseUrl
const csrf_token = req.headers['csrf-token'] as OrUndefined<string>
const xsrf_token = req.headers['xsrf-token'] as OrUndefined<string>
const x_csrf_token = req.headers['x-csrf-token'] as OrUndefined<string>
const x_xsrf_token = req.headers['x-xsrf-token'] as OrUndefined<string>
const token = csrf_token || xsrf_token || x_csrf_token || x_xsrf_token
if (CsurfMiddleware.options.ignoreRoutes!.includes(route)) {
return token || req.csrfToken()
}
return token
}
/**
* Enables [`csurf`][1].
*
* [1]: https://github.com/expressjs/csurf
*
* @param {Request} req - Incoming request
* @param {Response} res - Server response
* @param {NextFunction} next - Function to invoke next middleware function
* @return {void} Nothing when complete
*/
use(req: Request, res: Response, next: NextFunction): void {
return csurf({
...CsurfMiddleware.options,
value: CsurfMiddleware.extract as () => string
})(req, res, next)
}
}
export type CsurfOptions = {
cookie?: CookieOptions | boolean
ignoreMethods?: string[]
ignoreRoutes?: string[]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment