@fastify/cookie 8.1.0 → 8.3.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/README.md CHANGED
@@ -72,8 +72,8 @@ app.register(cookie, {
72
72
 
73
73
  ## Options
74
74
 
75
- - `secret` (`String` | `Array` | `Object`):
76
- - A `String` can be passed to use as secret to sign the cookie using [`cookie-signature`](http://npm.im/cookie-signature).
75
+ - `secret` (`String` | `Array` | `Buffer` | `Object`):
76
+ - A `String` or `Buffer` can be passed to use as secret to sign the cookie using [`cookie-signature`](http://npm.im/cookie-signature).
77
77
  - An `Array` can be passed if key rotation is desired. Read more about it in [Rotating signing secret](#rotating-secret).
78
78
  - More sophisticated cookie signing mechanisms can be implemented by supplying an `Object`. Read more about it in [Custom cookie signer](#custom-cookie-signer).
79
79
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastify/cookie",
3
- "version": "8.1.0",
3
+ "version": "8.3.0",
4
4
  "description": "Plugin for fastify to add support for cookies",
5
5
  "main": "plugin.js",
6
6
  "types": "types/plugin.d.ts",
@@ -47,7 +47,7 @@
47
47
  "snazzy": "^9.0.0",
48
48
  "standard": "^17.0.0",
49
49
  "tap": "^16.0.0",
50
- "tsd": "^0.22.0"
50
+ "tsd": "^0.24.1"
51
51
  },
52
52
  "dependencies": {
53
53
  "cookie": "^0.5.0",
package/plugin.js CHANGED
@@ -42,7 +42,7 @@ function fastifyCookieSetCookie (reply, name, value, options, signer) {
42
42
  }
43
43
 
44
44
  function fastifyCookieClearCookie (reply, name, options) {
45
- const opts = Object.assign({ path: '/' }, options || { }, {
45
+ const opts = Object.assign({ path: '/' }, options, {
46
46
  expires: new Date(1),
47
47
  signed: undefined,
48
48
  maxAge: undefined
@@ -88,9 +88,9 @@ function plugin (fastify, options, next) {
88
88
  if (hook === undefined) {
89
89
  return next(new Error('@fastify/cookie: Invalid value provided for the hook-option. You can set the hook-option only to false, \'onRequest\' , \'preParsing\' , \'preValidation\' or \'preHandler\''))
90
90
  }
91
- const enableRotation = Array.isArray(secret)
91
+ const isSigner = !secret || (typeof secret.sign === 'function' && typeof secret.unsign === 'function')
92
92
  const algorithm = options.algorithm || 'sha256'
93
- const signer = typeof secret === 'string' || enableRotation ? new Signer(secret, algorithm) : secret
93
+ const signer = isSigner ? secret : new Signer(secret, algorithm)
94
94
 
95
95
  fastify.decorate('parseCookie', parseCookie)
96
96
 
@@ -135,8 +135,9 @@ function plugin (fastify, options, next) {
135
135
  return fastifyCookieSetCookie(this, name, value, opts, signer)
136
136
  }
137
137
 
138
- function clearCookie (name, options) {
139
- return fastifyCookieClearCookie(this, name, options)
138
+ function clearCookie (name, cookieOptions) {
139
+ const opts = Object.assign({}, options.parseOptions, cookieOptions)
140
+ return fastifyCookieClearCookie(this, name, opts)
140
141
  }
141
142
  }
142
143
 
package/signer.js CHANGED
@@ -25,8 +25,8 @@ function Signer (secrets, algorithm = 'sha256') {
25
25
 
26
26
  function validateSecrets (secrets) {
27
27
  for (const secret of secrets) {
28
- if (typeof secret !== 'string') {
29
- throw new TypeError('Secret key must be a string.')
28
+ if (typeof secret !== 'string' && Buffer.isBuffer(secret) === false) {
29
+ throw new TypeError('Secret key must be a string or Buffer.')
30
30
  }
31
31
  }
32
32
  }
@@ -942,3 +942,51 @@ test('if cookies are not set, then the handler creates an empty req.cookies obje
942
942
  t.equal(res.statusCode, 200)
943
943
  })
944
944
  })
945
+
946
+ test('clearCookie should include parseOptions', (t) => {
947
+ t.plan(14)
948
+ const fastify = Fastify()
949
+ fastify.register(plugin, {
950
+ parseOptions: {
951
+ path: '/test',
952
+ domain: 'example.com'
953
+ }
954
+ })
955
+
956
+ const cookieOptions = {
957
+ path: '/test',
958
+ maxAge: 36000
959
+ }
960
+
961
+ fastify.get('/test1', (req, reply) => {
962
+ reply
963
+ .setCookie('foo', 'foo', cookieOptions)
964
+ .clearCookie('foo', cookieOptions)
965
+ .send({ hello: 'world' })
966
+ })
967
+
968
+ fastify.inject({
969
+ method: 'GET',
970
+ url: '/test1'
971
+ }, (err, res) => {
972
+ t.error(err)
973
+ t.equal(res.statusCode, 200)
974
+ t.same(JSON.parse(res.body), { hello: 'world' })
975
+
976
+ const cookies = res.cookies
977
+
978
+ t.equal(cookies.length, 2)
979
+ t.equal(cookies[0].name, 'foo')
980
+ t.equal(cookies[0].value, 'foo')
981
+ t.equal(cookies[0].maxAge, 36000)
982
+ t.equal(cookies[0].path, '/test')
983
+ t.equal(cookies[0].domain, 'example.com')
984
+
985
+ t.equal(cookies[1].name, 'foo')
986
+ t.equal(cookies[1].value, '')
987
+ t.equal(cookies[1].path, '/test')
988
+ t.equal(cookies[1].domain, 'example.com')
989
+
990
+ t.ok(new Date(cookies[1].expires) < new Date())
991
+ })
992
+ })
@@ -28,13 +28,15 @@ test('default', t => {
28
28
  })
29
29
 
30
30
  t.test('sign', (t) => {
31
- t.plan(3)
31
+ t.plan(5)
32
32
 
33
33
  const input = 'some-value'
34
34
  const result = signer.sign(input)
35
35
 
36
36
  t.equal(result, sign(input, secret))
37
37
  t.equal(result, sign(input, [secret]))
38
+ t.equal(result, sign(input, Buffer.from(secret)))
39
+ t.equal(result, sign(input, [Buffer.from(secret)]))
38
40
 
39
41
  t.throws(() => sign(undefined), 'Cookie value must be provided as a string.')
40
42
  })
@@ -61,7 +63,7 @@ test('default', t => {
61
63
  t.equal(result.renew, false)
62
64
  t.equal(result.value, 'some-value')
63
65
  t.same(result, unsign(input, [secret]))
64
- t.throws(() => unsign(undefined), 'Secret key must be a string.')
66
+ t.throws(() => unsign(undefined), 'Secret key must be a string or Buffer.')
65
67
  t.throws(() => unsign(undefined, secret), 'Signed cookie string must be provided.')
66
68
  })
67
69
  })
@@ -117,12 +119,14 @@ test('key rotation', (t) => {
117
119
  test('Signer', t => {
118
120
  t.plan(2)
119
121
 
120
- t.test('Signer needs a string as secret', (t) => {
121
- t.plan(4)
122
- t.throws(() => Signer(1), 'Secret key must be a string.')
123
- t.throws(() => Signer(undefined), 'Secret key must be a string.')
122
+ t.test('Signer needs a string or Buffer as secret', (t) => {
123
+ t.plan(6)
124
+ t.throws(() => Signer(1), 'Secret key must be a string or Buffer.')
125
+ t.throws(() => Signer(undefined), 'Secret key must be a string or Buffer.')
124
126
  t.doesNotThrow(() => Signer('secret'))
125
127
  t.doesNotThrow(() => Signer(['secret']))
128
+ t.doesNotThrow(() => Signer(Buffer.from('deadbeef76543210', 'hex')))
129
+ t.doesNotThrow(() => Signer([Buffer.from('deadbeef76543210', 'hex')]))
126
130
  })
127
131
 
128
132
  t.test('Signer handles algorithm properly', (t) => {
package/types/plugin.d.ts CHANGED
@@ -100,7 +100,7 @@ declare namespace fastifyCookie {
100
100
  }
101
101
 
102
102
  export class Signer implements SignerBase {
103
- constructor (secrets: string | Array<string>, algorithm?: string)
103
+ constructor (secrets: string | Array<string> | Buffer | Array<Buffer>, algorithm?: string)
104
104
  sign: (value: string) => string;
105
105
  unsign: (input: string) => UnsignResult;
106
106
  }
@@ -128,14 +128,14 @@ declare namespace fastifyCookie {
128
128
  type HookType = 'onRequest' | 'preParsing' | 'preValidation' | 'preHandler' | 'preSerialization';
129
129
 
130
130
  export interface FastifyCookieOptions {
131
- secret?: string | string[] | Signer;
131
+ secret?: string | string[] | Buffer | Buffer[] | Signer;
132
132
  hook?: HookType | false;
133
133
  parseOptions?: fastifyCookie.CookieSerializeOptions;
134
134
  }
135
135
 
136
- export type Sign = (value: string, secret: string, algorithm?: string) => string;
137
- export type Unsign = (input: string, secret: string, algorithm?: string) => UnsignResult;
138
- export type SignerFactory = (secrets: string | Array<string>, algorithm?: string) => SignerBase;
136
+ export type Sign = (value: string, secret: string | Buffer, algorithm?: string) => string;
137
+ export type Unsign = (input: string, secret: string | Buffer, algorithm?: string) => UnsignResult;
138
+ export type SignerFactory = (secrets: string | string[] | Buffer | Buffer[], algorithm?: string) => SignerBase;
139
139
 
140
140
  export interface UnsignResult {
141
141
  valid: boolean;
@@ -157,7 +157,7 @@ declare namespace fastifyCookie {
157
157
  export const fastifyCookie: FastifyCookie;
158
158
 
159
159
  export interface FastifyCookieOptions {
160
- secret?: string | string[] | SignerBase;
160
+ secret?: string | string[] | Buffer | Buffer[] | SignerBase;
161
161
  algorithm?: string;
162
162
  parseOptions?: CookieSerializeOptions;
163
163
  }
@@ -3,8 +3,7 @@ import { expectError, expectType } from 'tsd';
3
3
  import * as fastifyCookieStar from '..';
4
4
  import fastifyCookieCjsImport = require('..');
5
5
  import fastifyCookieDefault, { fastifyCookie as fastifyCookieNamed } from '..';
6
- import fastify, { FastifyInstance, FastifyPluginCallback, FastifyReply, setCookieWrapper } from 'fastify';
7
- import { Server } from 'http';
6
+ import fastify, { FastifyInstance, FastifyReply, setCookieWrapper } from 'fastify';
8
7
 
9
8
  const fastifyCookieCjs = require('..');
10
9
 
@@ -212,6 +211,8 @@ appWithCustomSigner.after(() => {
212
211
 
213
212
  new fastifyCookieStar.Signer('secretString')
214
213
  new fastifyCookieStar.Signer(['secretStringInArray'])
214
+ new fastifyCookieStar.Signer(Buffer.from('secretString'))
215
+ new fastifyCookieStar.Signer([Buffer.from('secretStringInArray')])
215
216
  const signer = new fastifyCookieStar.Signer(['secretStringInArray'], 'sha256')
216
217
  signer.sign('Lorem Ipsum')
217
218
  signer.unsign('Lorem Ipsum')