@fastify/cookie 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +13 -0
- package/.github/dependabot.yml +13 -0
- package/.github/stale.yml +21 -0
- package/.github/workflows/ci.yml +49 -0
- package/.taprc +3 -0
- package/LICENSE +21 -0
- package/README.md +206 -0
- package/cookie.js +225 -0
- package/package.json +62 -0
- package/plugin.d.ts +116 -0
- package/plugin.js +110 -0
- package/signer.js +32 -0
- package/test/cookie-module.test.js +205 -0
- package/test/cookie.test.js +703 -0
- package/test/plugin.test-d.ts +191 -0
- package/test/signer.test.js +79 -0
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const tap = require('tap')
|
|
4
|
+
const test = tap.test
|
|
5
|
+
const Fastify = require('fastify')
|
|
6
|
+
const sinon = require('sinon')
|
|
7
|
+
const cookieSignature = require('cookie-signature')
|
|
8
|
+
const plugin = require('../')
|
|
9
|
+
|
|
10
|
+
test('cookies get set correctly', (t) => {
|
|
11
|
+
t.plan(7)
|
|
12
|
+
const fastify = Fastify()
|
|
13
|
+
fastify.register(plugin)
|
|
14
|
+
|
|
15
|
+
fastify.get('/test1', (req, reply) => {
|
|
16
|
+
reply
|
|
17
|
+
.setCookie('foo', 'foo', { path: '/' })
|
|
18
|
+
.send({ hello: 'world' })
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
fastify.inject({
|
|
22
|
+
method: 'GET',
|
|
23
|
+
url: '/test1'
|
|
24
|
+
}, (err, res) => {
|
|
25
|
+
t.error(err)
|
|
26
|
+
t.equal(res.statusCode, 200)
|
|
27
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
28
|
+
|
|
29
|
+
const cookies = res.cookies
|
|
30
|
+
t.equal(cookies.length, 1)
|
|
31
|
+
t.equal(cookies[0].name, 'foo')
|
|
32
|
+
t.equal(cookies[0].value, 'foo')
|
|
33
|
+
t.equal(cookies[0].path, '/')
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('express cookie compatibility', (t) => {
|
|
38
|
+
t.plan(7)
|
|
39
|
+
const fastify = Fastify()
|
|
40
|
+
fastify.register(plugin)
|
|
41
|
+
|
|
42
|
+
fastify.get('/espresso', (req, reply) => {
|
|
43
|
+
reply
|
|
44
|
+
.cookie('foo', 'foo', { path: '/' })
|
|
45
|
+
.send({ hello: 'world' })
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
fastify.inject({
|
|
49
|
+
method: 'GET',
|
|
50
|
+
url: '/espresso'
|
|
51
|
+
}, (err, res) => {
|
|
52
|
+
t.error(err)
|
|
53
|
+
t.equal(res.statusCode, 200)
|
|
54
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
55
|
+
|
|
56
|
+
const cookies = res.cookies
|
|
57
|
+
t.equal(cookies.length, 1)
|
|
58
|
+
t.equal(cookies[0].name, 'foo')
|
|
59
|
+
t.equal(cookies[0].value, 'foo')
|
|
60
|
+
t.equal(cookies[0].path, '/')
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('should set multiple cookies', (t) => {
|
|
65
|
+
t.plan(10)
|
|
66
|
+
const fastify = Fastify()
|
|
67
|
+
fastify.register(plugin)
|
|
68
|
+
|
|
69
|
+
fastify.get('/', (req, reply) => {
|
|
70
|
+
reply
|
|
71
|
+
.setCookie('foo', 'foo')
|
|
72
|
+
.cookie('bar', 'test')
|
|
73
|
+
.setCookie('wee', 'woo')
|
|
74
|
+
.send({ hello: 'world' })
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
fastify.inject({
|
|
78
|
+
method: 'GET',
|
|
79
|
+
url: '/'
|
|
80
|
+
}, (err, res) => {
|
|
81
|
+
t.error(err)
|
|
82
|
+
t.equal(res.statusCode, 200)
|
|
83
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
84
|
+
|
|
85
|
+
const cookies = res.cookies
|
|
86
|
+
t.equal(cookies.length, 3)
|
|
87
|
+
t.equal(cookies[0].name, 'foo')
|
|
88
|
+
t.equal(cookies[0].value, 'foo')
|
|
89
|
+
t.equal(cookies[1].name, 'bar')
|
|
90
|
+
t.equal(cookies[1].value, 'test')
|
|
91
|
+
t.equal(cookies[2].name, 'wee')
|
|
92
|
+
t.equal(cookies[2].value, 'woo')
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('cookies get set correctly with millisecond dates', (t) => {
|
|
97
|
+
t.plan(8)
|
|
98
|
+
const fastify = Fastify()
|
|
99
|
+
fastify.register(plugin)
|
|
100
|
+
|
|
101
|
+
fastify.get('/test1', (req, reply) => {
|
|
102
|
+
reply
|
|
103
|
+
.setCookie('foo', 'foo', { path: '/', expires: Date.now() + 1000 })
|
|
104
|
+
.send({ hello: 'world' })
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
fastify.inject({
|
|
108
|
+
method: 'GET',
|
|
109
|
+
url: '/test1'
|
|
110
|
+
}, (err, res) => {
|
|
111
|
+
t.error(err)
|
|
112
|
+
t.equal(res.statusCode, 200)
|
|
113
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
114
|
+
|
|
115
|
+
const cookies = res.cookies
|
|
116
|
+
t.equal(cookies.length, 1)
|
|
117
|
+
t.equal(cookies[0].name, 'foo')
|
|
118
|
+
t.equal(cookies[0].value, 'foo')
|
|
119
|
+
t.equal(cookies[0].path, '/')
|
|
120
|
+
const expires = new Date(cookies[0].expires)
|
|
121
|
+
t.ok(expires < new Date(Date.now() + 5000))
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('share options for setCookie and clearCookie', (t) => {
|
|
126
|
+
t.plan(11)
|
|
127
|
+
const fastify = Fastify()
|
|
128
|
+
const secret = 'testsecret'
|
|
129
|
+
fastify.register(plugin, { secret })
|
|
130
|
+
|
|
131
|
+
const cookieOptions = {
|
|
132
|
+
signed: true,
|
|
133
|
+
maxAge: 36000
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fastify.get('/test1', (req, reply) => {
|
|
137
|
+
reply
|
|
138
|
+
.setCookie('foo', 'foo', cookieOptions)
|
|
139
|
+
.clearCookie('foo', cookieOptions)
|
|
140
|
+
.send({ hello: 'world' })
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
fastify.inject({
|
|
144
|
+
method: 'GET',
|
|
145
|
+
url: '/test1'
|
|
146
|
+
}, (err, res) => {
|
|
147
|
+
t.error(err)
|
|
148
|
+
t.equal(res.statusCode, 200)
|
|
149
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
150
|
+
|
|
151
|
+
const cookies = res.cookies
|
|
152
|
+
t.equal(cookies.length, 2)
|
|
153
|
+
t.equal(cookies[0].name, 'foo')
|
|
154
|
+
t.equal(cookies[0].value, cookieSignature.sign('foo', secret))
|
|
155
|
+
t.equal(cookies[0].maxAge, 36000)
|
|
156
|
+
|
|
157
|
+
t.equal(cookies[1].name, 'foo')
|
|
158
|
+
t.equal(cookies[1].value, '')
|
|
159
|
+
t.equal(cookies[1].path, '/')
|
|
160
|
+
t.ok(new Date(cookies[1].expires) < new Date())
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('expires should not be overridden in clearCookie', (t) => {
|
|
165
|
+
t.plan(11)
|
|
166
|
+
const fastify = Fastify()
|
|
167
|
+
const secret = 'testsecret'
|
|
168
|
+
fastify.register(plugin, { secret })
|
|
169
|
+
|
|
170
|
+
const cookieOptions = {
|
|
171
|
+
signed: true,
|
|
172
|
+
expires: Date.now() + 1000
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
fastify.get('/test1', (req, reply) => {
|
|
176
|
+
reply
|
|
177
|
+
.setCookie('foo', 'foo', cookieOptions)
|
|
178
|
+
.clearCookie('foo', cookieOptions)
|
|
179
|
+
.send({ hello: 'world' })
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
fastify.inject({
|
|
183
|
+
method: 'GET',
|
|
184
|
+
url: '/test1'
|
|
185
|
+
}, (err, res) => {
|
|
186
|
+
t.error(err)
|
|
187
|
+
t.equal(res.statusCode, 200)
|
|
188
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
189
|
+
|
|
190
|
+
const cookies = res.cookies
|
|
191
|
+
t.equal(cookies.length, 2)
|
|
192
|
+
t.equal(cookies[0].name, 'foo')
|
|
193
|
+
t.equal(cookies[0].value, cookieSignature.sign('foo', secret))
|
|
194
|
+
const expires = new Date(cookies[0].expires)
|
|
195
|
+
t.ok(expires < new Date(Date.now() + 5000))
|
|
196
|
+
|
|
197
|
+
t.equal(cookies[1].name, 'foo')
|
|
198
|
+
t.equal(cookies[1].value, '')
|
|
199
|
+
t.equal(cookies[1].path, '/')
|
|
200
|
+
t.equal(Number(cookies[1].expires), 0)
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
test('parses incoming cookies', (t) => {
|
|
205
|
+
t.plan(15)
|
|
206
|
+
const fastify = Fastify()
|
|
207
|
+
fastify.register(plugin)
|
|
208
|
+
|
|
209
|
+
// check that it parses the cookies in the onRequest hook
|
|
210
|
+
for (const hook of ['preValidation', 'preHandler']) {
|
|
211
|
+
fastify.addHook(hook, (req, reply, done) => {
|
|
212
|
+
t.ok(req.cookies)
|
|
213
|
+
t.ok(req.cookies.bar)
|
|
214
|
+
t.equal(req.cookies.bar, 'bar')
|
|
215
|
+
done()
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
fastify.addHook('preParsing', (req, reply, payload, done) => {
|
|
220
|
+
t.ok(req.cookies)
|
|
221
|
+
t.ok(req.cookies.bar)
|
|
222
|
+
t.equal(req.cookies.bar, 'bar')
|
|
223
|
+
done()
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
fastify.get('/test2', (req, reply) => {
|
|
227
|
+
t.ok(req.cookies)
|
|
228
|
+
t.ok(req.cookies.bar)
|
|
229
|
+
t.equal(req.cookies.bar, 'bar')
|
|
230
|
+
reply.send({ hello: 'world' })
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
fastify.inject({
|
|
234
|
+
method: 'GET',
|
|
235
|
+
url: '/test2',
|
|
236
|
+
headers: {
|
|
237
|
+
cookie: 'bar=bar'
|
|
238
|
+
}
|
|
239
|
+
}, (err, res) => {
|
|
240
|
+
t.error(err)
|
|
241
|
+
t.equal(res.statusCode, 200)
|
|
242
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
243
|
+
})
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
test('does not modify supplied cookie options object', (t) => {
|
|
247
|
+
t.plan(3)
|
|
248
|
+
const expireDate = Date.now() + 1000
|
|
249
|
+
const cookieOptions = {
|
|
250
|
+
path: '/',
|
|
251
|
+
expires: expireDate
|
|
252
|
+
}
|
|
253
|
+
const fastify = Fastify()
|
|
254
|
+
fastify.register(plugin)
|
|
255
|
+
|
|
256
|
+
fastify.get('/test1', (req, reply) => {
|
|
257
|
+
reply
|
|
258
|
+
.setCookie('foo', 'foo', cookieOptions)
|
|
259
|
+
.send({ hello: 'world' })
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
fastify.inject({
|
|
263
|
+
method: 'GET',
|
|
264
|
+
url: '/test1'
|
|
265
|
+
}, (err, res) => {
|
|
266
|
+
t.error(err)
|
|
267
|
+
t.equal(res.statusCode, 200)
|
|
268
|
+
t.strictSame(cookieOptions, {
|
|
269
|
+
path: '/',
|
|
270
|
+
expires: expireDate
|
|
271
|
+
})
|
|
272
|
+
})
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
test('cookies gets cleared correctly', (t) => {
|
|
276
|
+
t.plan(5)
|
|
277
|
+
const fastify = Fastify()
|
|
278
|
+
fastify.register(plugin)
|
|
279
|
+
|
|
280
|
+
fastify.get('/test1', (req, reply) => {
|
|
281
|
+
reply
|
|
282
|
+
.clearCookie('foo')
|
|
283
|
+
.send({ hello: 'world' })
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
fastify.inject({
|
|
287
|
+
method: 'GET',
|
|
288
|
+
url: '/test1'
|
|
289
|
+
}, (err, res) => {
|
|
290
|
+
t.error(err)
|
|
291
|
+
t.equal(res.statusCode, 200)
|
|
292
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
293
|
+
|
|
294
|
+
const cookies = res.cookies
|
|
295
|
+
t.equal(cookies.length, 1)
|
|
296
|
+
t.equal(new Date(cookies[0].expires) < new Date(), true)
|
|
297
|
+
})
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
test('cookies signature', (t) => {
|
|
301
|
+
t.plan(9)
|
|
302
|
+
|
|
303
|
+
t.test('unsign', t => {
|
|
304
|
+
t.plan(6)
|
|
305
|
+
const fastify = Fastify()
|
|
306
|
+
const secret = 'bar'
|
|
307
|
+
fastify.register(plugin, { secret })
|
|
308
|
+
|
|
309
|
+
fastify.get('/test1', (req, reply) => {
|
|
310
|
+
reply
|
|
311
|
+
.setCookie('foo', 'foo', { signed: true })
|
|
312
|
+
.send({ hello: 'world' })
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
fastify.inject({
|
|
316
|
+
method: 'GET',
|
|
317
|
+
url: '/test1'
|
|
318
|
+
}, (err, res) => {
|
|
319
|
+
t.error(err)
|
|
320
|
+
t.equal(res.statusCode, 200)
|
|
321
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
322
|
+
|
|
323
|
+
const cookies = res.cookies
|
|
324
|
+
t.equal(cookies.length, 1)
|
|
325
|
+
t.equal(cookies[0].name, 'foo')
|
|
326
|
+
t.equal(cookieSignature.unsign(cookies[0].value, secret), 'foo')
|
|
327
|
+
})
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
t.test('key rotation uses first key to sign', t => {
|
|
331
|
+
t.plan(6)
|
|
332
|
+
const fastify = Fastify()
|
|
333
|
+
const secret1 = 'secret-1'
|
|
334
|
+
const secret2 = 'secret-2'
|
|
335
|
+
fastify.register(plugin, { secret: [secret1, secret2] })
|
|
336
|
+
|
|
337
|
+
fastify.get('/test1', (req, reply) => {
|
|
338
|
+
reply
|
|
339
|
+
.setCookie('foo', 'cookieVal', { signed: true })
|
|
340
|
+
.send({ hello: 'world' })
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
fastify.inject({
|
|
344
|
+
method: 'GET',
|
|
345
|
+
url: '/test1'
|
|
346
|
+
}, (err, res) => {
|
|
347
|
+
t.error(err)
|
|
348
|
+
t.equal(res.statusCode, 200)
|
|
349
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
350
|
+
|
|
351
|
+
const cookies = res.cookies
|
|
352
|
+
t.equal(cookies.length, 1)
|
|
353
|
+
t.equal(cookies[0].name, 'foo')
|
|
354
|
+
t.equal(cookieSignature.unsign(cookies[0].value, secret1), 'cookieVal') // decode using first key
|
|
355
|
+
})
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
t.test('unsginCookie via fastify instance', t => {
|
|
359
|
+
t.plan(3)
|
|
360
|
+
const fastify = Fastify()
|
|
361
|
+
const secret = 'bar'
|
|
362
|
+
|
|
363
|
+
fastify.register(plugin, { secret })
|
|
364
|
+
|
|
365
|
+
fastify.get('/test1', (req, rep) => {
|
|
366
|
+
rep.send({
|
|
367
|
+
unsigned: fastify.unsignCookie(req.cookies.foo)
|
|
368
|
+
})
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
fastify.inject({
|
|
372
|
+
method: 'GET',
|
|
373
|
+
url: '/test1',
|
|
374
|
+
headers: {
|
|
375
|
+
cookie: `foo=${cookieSignature.sign('foo', secret)}`
|
|
376
|
+
}
|
|
377
|
+
}, (err, res) => {
|
|
378
|
+
t.error(err)
|
|
379
|
+
t.equal(res.statusCode, 200)
|
|
380
|
+
t.same(JSON.parse(res.body), { unsigned: { value: 'foo', renew: false, valid: true } })
|
|
381
|
+
})
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
t.test('unsignCookie via request decorator', t => {
|
|
385
|
+
t.plan(3)
|
|
386
|
+
const fastify = Fastify()
|
|
387
|
+
const secret = 'bar'
|
|
388
|
+
fastify.register(plugin, { secret })
|
|
389
|
+
|
|
390
|
+
fastify.get('/test1', (req, reply) => {
|
|
391
|
+
reply.send({
|
|
392
|
+
unsigned: req.unsignCookie(req.cookies.foo)
|
|
393
|
+
})
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
fastify.inject({
|
|
397
|
+
method: 'GET',
|
|
398
|
+
url: '/test1',
|
|
399
|
+
headers: {
|
|
400
|
+
cookie: `foo=${cookieSignature.sign('foo', secret)}`
|
|
401
|
+
}
|
|
402
|
+
}, (err, res) => {
|
|
403
|
+
t.error(err)
|
|
404
|
+
t.equal(res.statusCode, 200)
|
|
405
|
+
t.same(JSON.parse(res.body), { unsigned: { value: 'foo', renew: false, valid: true } })
|
|
406
|
+
})
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
t.test('unsignCookie via reply decorator', t => {
|
|
410
|
+
t.plan(3)
|
|
411
|
+
const fastify = Fastify()
|
|
412
|
+
const secret = 'bar'
|
|
413
|
+
fastify.register(plugin, { secret })
|
|
414
|
+
|
|
415
|
+
fastify.get('/test1', (req, reply) => {
|
|
416
|
+
reply.send({
|
|
417
|
+
unsigned: reply.unsignCookie(req.cookies.foo)
|
|
418
|
+
})
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
fastify.inject({
|
|
422
|
+
method: 'GET',
|
|
423
|
+
url: '/test1',
|
|
424
|
+
headers: {
|
|
425
|
+
cookie: `foo=${cookieSignature.sign('foo', secret)}`
|
|
426
|
+
}
|
|
427
|
+
}, (err, res) => {
|
|
428
|
+
t.error(err)
|
|
429
|
+
t.equal(res.statusCode, 200)
|
|
430
|
+
t.same(JSON.parse(res.body), { unsigned: { value: 'foo', renew: false, valid: true } })
|
|
431
|
+
})
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
t.test('unsignCookie via request decorator after rotation', t => {
|
|
435
|
+
t.plan(3)
|
|
436
|
+
const fastify = Fastify()
|
|
437
|
+
const secret1 = 'sec-1'
|
|
438
|
+
const secret2 = 'sec-2'
|
|
439
|
+
fastify.register(plugin, { secret: [secret1, secret2] })
|
|
440
|
+
|
|
441
|
+
fastify.get('/test1', (req, reply) => {
|
|
442
|
+
reply.send({
|
|
443
|
+
unsigned: req.unsignCookie(req.cookies.foo)
|
|
444
|
+
})
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
fastify.inject({
|
|
448
|
+
method: 'GET',
|
|
449
|
+
url: '/test1',
|
|
450
|
+
headers: {
|
|
451
|
+
cookie: `foo=${cookieSignature.sign('foo', secret2)}`
|
|
452
|
+
}
|
|
453
|
+
}, (err, res) => {
|
|
454
|
+
t.error(err)
|
|
455
|
+
t.equal(res.statusCode, 200)
|
|
456
|
+
t.same(JSON.parse(res.body), { unsigned: { value: 'foo', renew: true, valid: true } })
|
|
457
|
+
})
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
t.test('unsignCookie via reply decorator after rotation', t => {
|
|
461
|
+
t.plan(3)
|
|
462
|
+
const fastify = Fastify()
|
|
463
|
+
const secret1 = 'sec-1'
|
|
464
|
+
const secret2 = 'sec-2'
|
|
465
|
+
fastify.register(plugin, { secret: [secret1, secret2] })
|
|
466
|
+
|
|
467
|
+
fastify.get('/test1', (req, reply) => {
|
|
468
|
+
reply.send({
|
|
469
|
+
unsigned: reply.unsignCookie(req.cookies.foo)
|
|
470
|
+
})
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
fastify.inject({
|
|
474
|
+
method: 'GET',
|
|
475
|
+
url: '/test1',
|
|
476
|
+
headers: {
|
|
477
|
+
cookie: `foo=${cookieSignature.sign('foo', secret2)}`
|
|
478
|
+
}
|
|
479
|
+
}, (err, res) => {
|
|
480
|
+
t.error(err)
|
|
481
|
+
t.equal(res.statusCode, 200)
|
|
482
|
+
t.same(JSON.parse(res.body), { unsigned: { value: 'foo', renew: true, valid: true } })
|
|
483
|
+
})
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
t.test('unsignCookie via request decorator failure response', t => {
|
|
487
|
+
t.plan(3)
|
|
488
|
+
const fastify = Fastify()
|
|
489
|
+
const secret1 = 'sec-1'
|
|
490
|
+
const secret2 = 'sec-2'
|
|
491
|
+
fastify.register(plugin, { secret: [secret1, secret2] })
|
|
492
|
+
|
|
493
|
+
fastify.get('/test1', (req, reply) => {
|
|
494
|
+
reply.send({
|
|
495
|
+
unsigned: req.unsignCookie(req.cookies.foo)
|
|
496
|
+
})
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
fastify.inject({
|
|
500
|
+
method: 'GET',
|
|
501
|
+
url: '/test1',
|
|
502
|
+
headers: {
|
|
503
|
+
cookie: `foo=${cookieSignature.sign('foo', 'invalid-secret')}`
|
|
504
|
+
}
|
|
505
|
+
}, (err, res) => {
|
|
506
|
+
t.error(err)
|
|
507
|
+
t.equal(res.statusCode, 200)
|
|
508
|
+
t.same(JSON.parse(res.body), { unsigned: { value: null, renew: false, valid: false } })
|
|
509
|
+
})
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
t.test('unsignCookie reply decorator failure response', t => {
|
|
513
|
+
t.plan(3)
|
|
514
|
+
const fastify = Fastify()
|
|
515
|
+
const secret1 = 'sec-1'
|
|
516
|
+
const secret2 = 'sec-2'
|
|
517
|
+
fastify.register(plugin, { secret: [secret1, secret2] })
|
|
518
|
+
|
|
519
|
+
fastify.get('/test1', (req, reply) => {
|
|
520
|
+
reply.send({
|
|
521
|
+
unsigned: reply.unsignCookie(req.cookies.foo)
|
|
522
|
+
})
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
fastify.inject({
|
|
526
|
+
method: 'GET',
|
|
527
|
+
url: '/test1',
|
|
528
|
+
headers: {
|
|
529
|
+
cookie: `foo=${cookieSignature.sign('foo', 'invalid-secret')}`
|
|
530
|
+
}
|
|
531
|
+
}, (err, res) => {
|
|
532
|
+
t.error(err)
|
|
533
|
+
t.equal(res.statusCode, 200)
|
|
534
|
+
t.same(JSON.parse(res.body), { unsigned: { value: null, renew: false, valid: false } })
|
|
535
|
+
})
|
|
536
|
+
})
|
|
537
|
+
})
|
|
538
|
+
|
|
539
|
+
test('custom signer', t => {
|
|
540
|
+
t.plan(7)
|
|
541
|
+
const fastify = Fastify()
|
|
542
|
+
const signStub = sinon.stub().returns('SIGNED-VALUE')
|
|
543
|
+
const unsignStub = sinon.stub().returns('ORIGINAL VALUE')
|
|
544
|
+
const secret = { sign: signStub, unsign: unsignStub }
|
|
545
|
+
fastify.register(plugin, { secret })
|
|
546
|
+
|
|
547
|
+
fastify.get('/test1', (req, reply) => {
|
|
548
|
+
reply
|
|
549
|
+
.setCookie('foo', 'bar', { signed: true })
|
|
550
|
+
.send({ hello: 'world' })
|
|
551
|
+
})
|
|
552
|
+
|
|
553
|
+
fastify.inject({
|
|
554
|
+
method: 'GET',
|
|
555
|
+
url: '/test1'
|
|
556
|
+
}, (err, res) => {
|
|
557
|
+
t.error(err)
|
|
558
|
+
t.equal(res.statusCode, 200)
|
|
559
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
560
|
+
|
|
561
|
+
const cookies = res.cookies
|
|
562
|
+
t.equal(cookies.length, 1)
|
|
563
|
+
t.equal(cookies[0].name, 'foo')
|
|
564
|
+
t.equal(cookies[0].value, 'SIGNED-VALUE')
|
|
565
|
+
t.ok(signStub.calledOnceWithExactly('bar'))
|
|
566
|
+
})
|
|
567
|
+
})
|
|
568
|
+
|
|
569
|
+
test('unsignCookie decorator with custom signer', t => {
|
|
570
|
+
t.plan(4)
|
|
571
|
+
const fastify = Fastify()
|
|
572
|
+
const signStub = sinon.stub().returns('SIGNED-VALUE')
|
|
573
|
+
const unsignStub = sinon.stub().returns('ORIGINAL VALUE')
|
|
574
|
+
const secret = { sign: signStub, unsign: unsignStub }
|
|
575
|
+
fastify.register(plugin, { secret })
|
|
576
|
+
|
|
577
|
+
fastify.get('/test1', (req, reply) => {
|
|
578
|
+
reply.send({
|
|
579
|
+
unsigned: reply.unsignCookie(req.cookies.foo)
|
|
580
|
+
})
|
|
581
|
+
})
|
|
582
|
+
|
|
583
|
+
fastify.inject({
|
|
584
|
+
method: 'GET',
|
|
585
|
+
url: '/test1',
|
|
586
|
+
headers: {
|
|
587
|
+
cookie: 'foo=SOME-SIGNED-VALUE'
|
|
588
|
+
}
|
|
589
|
+
}, (err, res) => {
|
|
590
|
+
t.error(err)
|
|
591
|
+
t.equal(res.statusCode, 200)
|
|
592
|
+
t.same(JSON.parse(res.body), { unsigned: 'ORIGINAL VALUE' })
|
|
593
|
+
t.ok(unsignStub.calledOnceWithExactly('SOME-SIGNED-VALUE'))
|
|
594
|
+
})
|
|
595
|
+
})
|
|
596
|
+
|
|
597
|
+
test('pass options to `cookies.parse`', (t) => {
|
|
598
|
+
t.plan(6)
|
|
599
|
+
const fastify = Fastify()
|
|
600
|
+
fastify.register(plugin, {
|
|
601
|
+
parseOptions: {
|
|
602
|
+
decode: decoder
|
|
603
|
+
}
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
fastify.get('/test1', (req, reply) => {
|
|
607
|
+
t.ok(req.cookies)
|
|
608
|
+
t.ok(req.cookies.foo)
|
|
609
|
+
t.equal(req.cookies.foo, 'bartest')
|
|
610
|
+
reply.send({ hello: 'world' })
|
|
611
|
+
})
|
|
612
|
+
|
|
613
|
+
fastify.inject({
|
|
614
|
+
method: 'GET',
|
|
615
|
+
url: '/test1',
|
|
616
|
+
headers: {
|
|
617
|
+
cookie: 'foo=bar'
|
|
618
|
+
}
|
|
619
|
+
}, (err, res) => {
|
|
620
|
+
t.error(err)
|
|
621
|
+
t.equal(res.statusCode, 200)
|
|
622
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
623
|
+
})
|
|
624
|
+
|
|
625
|
+
function decoder (str) {
|
|
626
|
+
return str + 'test'
|
|
627
|
+
}
|
|
628
|
+
})
|
|
629
|
+
|
|
630
|
+
test('issue 53', (t) => {
|
|
631
|
+
t.plan(5)
|
|
632
|
+
const fastify = Fastify()
|
|
633
|
+
fastify.register(plugin)
|
|
634
|
+
|
|
635
|
+
let cookies
|
|
636
|
+
let count = 1
|
|
637
|
+
fastify.get('/foo', (req, reply) => {
|
|
638
|
+
if (count > 1) {
|
|
639
|
+
t.not(cookies, req.cookies)
|
|
640
|
+
return reply.send('done')
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
count += 1
|
|
644
|
+
cookies = req.cookies
|
|
645
|
+
reply.send('done')
|
|
646
|
+
})
|
|
647
|
+
|
|
648
|
+
fastify.inject({ url: '/foo' }, (err, response) => {
|
|
649
|
+
t.error(err)
|
|
650
|
+
t.equal(response.body, 'done')
|
|
651
|
+
})
|
|
652
|
+
|
|
653
|
+
fastify.inject({ url: '/foo' }, (err, response) => {
|
|
654
|
+
t.error(err)
|
|
655
|
+
t.equal(response.body, 'done')
|
|
656
|
+
})
|
|
657
|
+
})
|
|
658
|
+
|
|
659
|
+
test('parse cookie manually using decorator', (t) => {
|
|
660
|
+
t.plan(2)
|
|
661
|
+
const fastify = Fastify()
|
|
662
|
+
fastify.register(plugin)
|
|
663
|
+
|
|
664
|
+
fastify.ready(() => {
|
|
665
|
+
t.ok(fastify.parseCookie)
|
|
666
|
+
t.same(fastify.parseCookie('foo=bar', {}), { foo: 'bar' })
|
|
667
|
+
t.end()
|
|
668
|
+
})
|
|
669
|
+
})
|
|
670
|
+
|
|
671
|
+
test('cookies set with plugin options parseOptions field', (t) => {
|
|
672
|
+
t.plan(8)
|
|
673
|
+
const fastify = Fastify()
|
|
674
|
+
fastify.register(plugin, {
|
|
675
|
+
parseOptions: {
|
|
676
|
+
path: '/test',
|
|
677
|
+
domain: 'example.com'
|
|
678
|
+
}
|
|
679
|
+
})
|
|
680
|
+
|
|
681
|
+
fastify.get('/test', (req, reply) => {
|
|
682
|
+
reply.setCookie('foo', 'foo').send({ hello: 'world' })
|
|
683
|
+
})
|
|
684
|
+
|
|
685
|
+
fastify.inject(
|
|
686
|
+
{
|
|
687
|
+
method: 'GET',
|
|
688
|
+
url: '/test'
|
|
689
|
+
},
|
|
690
|
+
(err, res) => {
|
|
691
|
+
t.error(err)
|
|
692
|
+
t.equal(res.statusCode, 200)
|
|
693
|
+
t.same(JSON.parse(res.body), { hello: 'world' })
|
|
694
|
+
|
|
695
|
+
const cookies = res.cookies
|
|
696
|
+
t.equal(cookies.length, 1)
|
|
697
|
+
t.equal(cookies[0].name, 'foo')
|
|
698
|
+
t.equal(cookies[0].value, 'foo')
|
|
699
|
+
t.equal(cookies[0].path, '/test')
|
|
700
|
+
t.equal(cookies[0].domain, 'example.com')
|
|
701
|
+
}
|
|
702
|
+
)
|
|
703
|
+
})
|