mirror of
https://github.com/overleaf/overleaf.git
synced 2024-10-24 21:12:38 -04:00
e82a053c85
[misc] move admin capability from www. to admin. subdomain GitOrigin-RevId: e0daeacf3c06b856ffb9fd35dce76e71f14e8459
113 lines
3.4 KiB
JavaScript
113 lines
3.4 KiB
JavaScript
/* eslint-disable
|
|
max-len,
|
|
no-return-assign,
|
|
no-unused-vars,
|
|
*/
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
// Fix any style issues and re-enable lint.
|
|
/*
|
|
* decaffeinate suggestions:
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
* DS207: Consider shorter variations of null checks
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
*/
|
|
|
|
const csurf = require('csurf')
|
|
const csrf = csurf()
|
|
const { promisify } = require('util')
|
|
const Settings = require('@overleaf/settings')
|
|
const logger = require('@overleaf/logger')
|
|
|
|
// Wrapper for `csurf` middleware that provides a list of routes that can be excluded from csrf checks.
|
|
//
|
|
// Include with `Csrf = require('./Csrf')`
|
|
//
|
|
// Add the middleware to the router with:
|
|
// myRouter.csrf = new Csrf()
|
|
// myRouter.use webRouter.csrf.middleware
|
|
// When building routes, specify a route to exclude from csrf checks with:
|
|
// myRouter.csrf.disableDefaultCsrfProtection "/path" "METHOD"
|
|
//
|
|
// To validate the csrf token in a request to ensure that it's valid, you can use `validateRequest`, which takes a
|
|
// request object and calls a callback with an error if invalid.
|
|
|
|
class Csrf {
|
|
constructor() {
|
|
this.middleware = this.middleware.bind(this)
|
|
this.excluded_routes = {}
|
|
}
|
|
|
|
static blockCrossOriginRequests() {
|
|
return function (req, res, next) {
|
|
const { origin } = req.headers
|
|
// NOTE: Only cross-origin requests must have an origin header set.
|
|
if (origin && !Settings.allowedOrigins.includes(origin)) {
|
|
logger.warn({ req }, 'blocking cross-origin request')
|
|
return res.sendStatus(403)
|
|
}
|
|
next()
|
|
}
|
|
}
|
|
|
|
disableDefaultCsrfProtection(route, method) {
|
|
if (!this.excluded_routes[route]) {
|
|
this.excluded_routes[route] = {}
|
|
}
|
|
return (this.excluded_routes[route][method] = 1)
|
|
}
|
|
|
|
middleware(req, res, next) {
|
|
// We want to call the middleware for all routes, even if excluded, because csurf sets up a csrfToken() method on
|
|
// the request, to get a new csrf token for any rendered forms. For excluded routes we'll then ignore a 'bad csrf
|
|
// token' error from csurf and continue on...
|
|
|
|
// check whether the request method is excluded for the specified route
|
|
if (
|
|
(this.excluded_routes[req.path] != null
|
|
? this.excluded_routes[req.path][req.method]
|
|
: undefined) === 1
|
|
) {
|
|
// ignore the error if it's due to a bad csrf token, and continue
|
|
return csrf(req, res, err => {
|
|
if (err && err.code !== 'EBADCSRFTOKEN') {
|
|
return next(err)
|
|
} else {
|
|
return next()
|
|
}
|
|
})
|
|
} else {
|
|
return csrf(req, res, next)
|
|
}
|
|
}
|
|
|
|
static validateRequest(req, cb) {
|
|
// run a dummy csrf check to see if it returns an error
|
|
if (cb == null) {
|
|
cb = function (valid) {}
|
|
}
|
|
return csrf(req, null, err => cb(err))
|
|
}
|
|
|
|
static validateToken(token, session, cb) {
|
|
if (token == null) {
|
|
return cb(new Error('missing token'))
|
|
}
|
|
// run a dummy csrf check to see if it returns an error
|
|
// use this to simulate a csrf check regardless of req method, headers &c.
|
|
const req = {
|
|
body: {
|
|
_csrf: token,
|
|
},
|
|
headers: {},
|
|
method: 'POST',
|
|
session,
|
|
}
|
|
return Csrf.validateRequest(req, cb)
|
|
}
|
|
}
|
|
|
|
Csrf.promises = {
|
|
validateRequest: promisify(Csrf.validateRequest),
|
|
}
|
|
|
|
module.exports = Csrf
|