3 var env = require('gitter-web-env');
5 var logger = env.logger;
6 var debug = require('debug')('gitter:infra:enforce-csrf-middleware');
7 var StatusError = require('statuserror');
9 var escapeRegExp = require('../../utils/escape-regexp');
12 '/api/private/fixtures',
14 '/api/private/transloadit/',
15 '/api/private/statsc',
18 '/login/oauth/authorize/decision',
19 '/api/private/subscription/'
22 if (env.config.get('ws:startFayeInPrimaryApp')) {
23 ALLOWLIST.push('/faye');
24 ALLOWLIST.push('/bayeux');
27 var ALLOWLIST_REGEXP = new RegExp('^(' + ALLOWLIST.map(escapeRegExp).join('|') + ')');
29 module.exports = function(req, res, next) {
30 // ignore these methods, they shouldnt alter state
31 if (req.method === 'GET' || req.method === 'HEAD' || req.method === 'OPTIONS') return next();
33 /* OAuth clients have req.authInfo. Aways let them through */
34 if (req.authInfo) return next();
36 if (isInAllowlist(req)) {
37 debug('skipping csrf check for %s', req.path);
41 var clientToken = getClientToken(req);
43 stats.event('token.rejected.notpresented');
45 'csrf: Rejecting client ' + req.ip + ' request to ' + req.path + ' as they presented no token'
47 return next(new StatusError(403));
50 if (req.accessToken !== clientToken) {
51 stats.event('token.rejected.mismatch');
55 'csrf: Rejecting client ' +
59 ' as they presented an illegal token',
61 serverAccessToken: req.accessToken,
62 clientToken: clientToken,
63 username: req.user.username,
69 'csrf: Rejecting client ' +
73 ' as they are probably logged out',
75 serverAccessToken: req.accessToken,
76 clientToken: clientToken
81 return next(new StatusError(403));
87 function isInAllowlist(req) {
88 return ALLOWLIST_REGEXP.test(req.path);
91 function getClientToken(req) {
93 (req.body && req.body.accessToken) ||
94 (req.query && req.query.accessToken) ||
95 req.headers['x-access-token'] ||
96 req.headers['x-csrf-token'] ||
97 req.headers['x-xsrf-token']