Csrf.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. no-unused-vars,
  5. standard/no-callback-literal,
  6. */
  7. // TODO: This file was created by bulk-decaffeinate.
  8. // Fix any style issues and re-enable lint.
  9. /*
  10. * decaffeinate suggestions:
  11. * DS102: Remove unnecessary code created because of implicit returns
  12. * DS207: Consider shorter variations of null checks
  13. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  14. */
  15. const csurf = require('csurf')
  16. const csrf = csurf()
  17. const { promisify } = require('util')
  18. // Wrapper for `csurf` middleware that provides a list of routes that can be excluded from csrf checks.
  19. //
  20. // Include with `Csrf = require('./Csrf')`
  21. //
  22. // Add the middleware to the router with:
  23. // myRouter.csrf = new Csrf()
  24. // myRouter.use webRouter.csrf.middleware
  25. // When building routes, specify a route to exclude from csrf checks with:
  26. // myRouter.csrf.disableDefaultCsrfProtection "/path" "METHOD"
  27. //
  28. // To validate the csrf token in a request to ensure that it's valid, you can use `validateRequest`, which takes a
  29. // request object and calls a callback with an error if invalid.
  30. class Csrf {
  31. constructor() {
  32. this.middleware = this.middleware.bind(this)
  33. this.excluded_routes = {}
  34. }
  35. disableDefaultCsrfProtection(route, method) {
  36. if (!this.excluded_routes[route]) {
  37. this.excluded_routes[route] = {}
  38. }
  39. return (this.excluded_routes[route][method] = 1)
  40. }
  41. middleware(req, res, next) {
  42. // We want to call the middleware for all routes, even if excluded, because csurf sets up a csrfToken() method on
  43. // the request, to get a new csrf token for any rendered forms. For excluded routes we'll then ignore a 'bad csrf
  44. // token' error from csurf and continue on...
  45. // check whether the request method is excluded for the specified route
  46. if (
  47. (this.excluded_routes[req.path] != null
  48. ? this.excluded_routes[req.path][req.method]
  49. : undefined) === 1
  50. ) {
  51. // ignore the error if it's due to a bad csrf token, and continue
  52. return csrf(req, res, err => {
  53. if (err && err.code !== 'EBADCSRFTOKEN') {
  54. return next(err)
  55. } else {
  56. return next()
  57. }
  58. })
  59. } else {
  60. return csrf(req, res, next)
  61. }
  62. }
  63. static validateRequest(req, cb) {
  64. // run a dummy csrf check to see if it returns an error
  65. if (cb == null) {
  66. cb = function(valid) {}
  67. }
  68. return csrf(req, null, err => cb(err))
  69. }
  70. static validateToken(token, session, cb) {
  71. if (token == null) {
  72. return cb(new Error('missing token'))
  73. }
  74. // run a dummy csrf check to see if it returns an error
  75. // use this to simulate a csrf check regardless of req method, headers &c.
  76. const req = {
  77. body: {
  78. _csrf: token
  79. },
  80. headers: {},
  81. method: 'POST',
  82. session
  83. }
  84. return Csrf.validateRequest(req, cb)
  85. }
  86. }
  87. Csrf.promises = {
  88. validateRequest: promisify(Csrf.validateRequest)
  89. }
  90. module.exports = Csrf