Fix (hopefully) CSRF for SPA

This commit is contained in:
Jerko Steiner 2019-03-17 15:04:15 +05:00
parent 0c7af3538c
commit 428630072c
6 changed files with 54 additions and 8 deletions

19
package-lock.json generated
View File

@ -1418,6 +1418,15 @@
"@types/node": "*"
}
},
"@types/cookie-parser": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.1.tgz",
"integrity": "sha512-iJY6B3ZGufLiDf2OCAgiAAQuj1sMKC/wz/7XCEjZ+/MDuultfFJuSwrBKcLSmJ5iYApLzCCYBYJZs0Ws8GPmwA==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/cookiejar": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.1.tgz",
@ -4044,6 +4053,16 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
},
"cookie-parser": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz",
"integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==",
"dev": true,
"requires": {
"cookie": "0.3.1",
"cookie-signature": "1.0.6"
}
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",

View File

@ -11,6 +11,7 @@
"@types/bcrypt": "^3.0.0",
"@types/body-parser": "^1.17.0",
"@types/cls-hooked": "^4.2.1",
"@types/cookie-parser": "^1.4.1",
"@types/csurf": "^1.9.35",
"@types/es6-shim": "^0.31.39",
"@types/express": "^4.16.1",
@ -35,6 +36,7 @@
"browserify": "^16.2.3",
"buildfile": "^1.2.20",
"bulma": "^0.7.4",
"cookie-parser": "^1.4.4",
"history": "^4.9.0",
"jest": "^24.5.0",
"lerna": "^3.13.1",

View File

@ -3,6 +3,7 @@ import * as routes from '../routes'
import * as services from '../services'
import * as team from '../team'
import * as user from '../user'
import cookieParser from 'cookie-parser'
import express from 'express'
import {AsyncRouter, TransactionalRouter} from '../router'
import {IApplication} from './IApplication'
@ -71,7 +72,11 @@ export class Application implements IApplication {
}).handle)
router.use(new middleware.RequestLogger(apiLogger).handle)
router.use(json())
router.use(middleware.csrf)
router.use(cookieParser(this.config.app.session.secret))
router.use(new middleware.CSRFMiddleware({
baseUrl: this.config.app.baseUrl,
cookieName: this.config.app.session.name + '_csrf',
}).handle)
router.use(new middleware.Transaction(this.database.namespace).handle)
router.use(this.authenticator.handle)

View File

@ -0,0 +1,26 @@
import Csurf from 'csurf'
import {IHandler} from './IHandler'
import {IMiddleware} from './IMiddleware'
import {UrlWithStringQuery} from 'url'
export interface ICSRFParams {
baseUrl: UrlWithStringQuery
cookieName: string
}
export class CSRFMiddleware implements IMiddleware {
readonly handle: IHandler
constructor(readonly params: ICSRFParams) {
this.handle = Csurf({
cookie: {
signed: true,
httpOnly: true,
sameSite: true,
secure: params.baseUrl.protocol === 'https',
path: params.baseUrl.path,
key: params.cookieName,
},
})
}
}

View File

@ -1,6 +0,0 @@
import Csurf from 'csurf'
import {IHandler} from './IHandler'
export const csrf: IHandler = Csurf({
sessionKey: 'session',
})

View File

@ -1,5 +1,5 @@
export * from './Authenticator'
export * from './csrf'
export * from './CSRFMiddleware'
export * from './ensureLoggedIn'
export * from './ErrorApiHandler'
export * from './ErrorPageHandler'