UNPKG

electrode-csrf-jwt

Version:

Stateless Cross-Site Request Forgery (CSRF) protection with JWT

81 lines (65 loc) 2.02 kB
"use strict"; /* eslint-disable complexity */ const JwtTokenEngine = require("./jwt-token-engine"); const HashTokenEngine = require("./hash-token-engine"); const constants = require("./constants"); const errors = require("./errors"); class CSRF { constructor(options) { const falseCb = () => false; this._skipCreate = options.skipCreate || falseCb; this._skipVerify = options.skipVerify || falseCb; this._shouldSkip = options.shouldSkip || falseCb; this.cookieName = options.cookieName || constants.cookieName; this.headerName = options.headerName || this.cookieName; this.engine = options.tokenEngine === "hash" ? new HashTokenEngine(options) : new JwtTokenEngine(options); } create(payload) { return this.engine.create(payload); } verify(header, cookie) { return this.engine.verify(header, cookie); } process(ctx, routeConfig) { const method = ctx.method.toUpperCase(); // completely skip the CSRF process if ( method === "OPTIONS" || method === "TRACE" || this._shouldSkip(ctx.request) || routeConfig.enabled === false || routeConfig.shouldSkip === true ) { return ctx.continue(); } const createToken = () => { if (this._skipCreate(ctx.request) || routeConfig.skipCreate === true) { return; } ctx.create(); }; // Skip verify for HTTP GET/HEAD or if user indicate skip verify if ( method === "GET" || method === "HEAD" || this._skipVerify(ctx.request) || routeConfig.skipVerify === true ) { createToken(); return ctx.continue(); } // verify and create new CSRF tokens const verify = ctx.verify(); createToken(); if (verify.error) { return ctx.error(verify); } if (ctx.firstPost && routeConfig.allowFirstPost !== true) { verify.error = new Error(errors.FIRST_POST_NOT_ALLOWED); return ctx.error(verify); } return ctx.continue(); } } module.exports = CSRF;