forked from koajs/csrf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
117 lines (99 loc) · 2.56 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
exports = module.exports = function (app, opts) {
if (isApp(app)) {
opts = opts || {}
} else {
opts = app || {}
app = null
}
var tokens = require('csrf-tokens')(opts)
var middleware = opts.middleware || exports.middleware
if (app) {
define(app)
return app
}
return function* csrf(next) {
define(this)
yield* middleware.call(this, next)
}
function define(ctx) {
var context = ctx.context || ctx
var response = ctx.response
var request = ctx.request
/*
* Lazily creates a CSRF token.
* Creates one per request.
*
* @api public
*/
context.__defineGetter__('csrf', function () {
if (this._csrf) return this._csrf
var secret = this.session.secret
|| (this.session.secret = tokens.secretSync())
return this._csrf = tokens.create(secret)
})
response.__defineGetter__('csrf', function () {
return this.ctx.csrf
})
/**
* Asserts that a CSRF token exists and is valid.
* Throws a 403 error otherwise.
* var body = yield* this.request.json()
* try {
* this.assertCSRF(body)
* } catch (err) {
* this.status = 403
* this.body = {
* message: 'invalid CSRF token'
* }
* }
*
* @param {Object} body
* @return {Context} this
* @api public
**/
context.assertCSRF =
context.assertCsrf = function (body) {
// no session
var secret = this.session.secret
if (!secret) this.throw(403, 'invalid csrf token')
var token = (body && body._csrf)
|| (body && body.fields._csrf) // **** koa-better-body will return body.fields._csrf ****
|| (this.query && this.query._csrf)
|| (this.get('x-csrf-token'))
|| (this.get('x-xsrf-token'))
|| body
if (!tokens.verify(secret, token)) this.throw(403, 'invalid csrf token')
return this
}
request.assertCSRF =
request.assertCsrf = function (body) {
this.ctx.assertCsrf(body)
return this
}
}
}
/**
* a middleware to handle csrf check
*
* @api public
*/
exports.middleware = function* (next) {
// ignore get, head, options
if (this.method === 'GET'
|| this.method === 'HEAD'
|| this.method === 'OPTIONS') {
return yield* next
}
// bodyparser middlewares maybe store body in request.body
// or you can just set csrf token header
this.assertCSRF(this.request.body)
yield* next
}
/**
* check if is koa app instance
*
* @api private
*/
function isApp(app) {
return app && app.context && app.response && app.request
}