@fastify/cookie 7.3.1 → 7.4.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.
@@ -14,4 +14,5 @@ jobs:
14
14
  test:
15
15
  uses: fastify/workflows/.github/workflows/plugins-ci.yml@v3
16
16
  with:
17
+ license-check: true
17
18
  lint: true
package/README.md CHANGED
@@ -236,12 +236,12 @@ test('Request requires signed cookie', async () => {
236
236
 
237
237
  ### Manual signing/unsigning with low level utilities
238
238
 
239
- with signerFactory
239
+ with Signer
240
240
 
241
241
  ```js
242
- const { fastifyCookie } = require('@fastify/cookie');
242
+ const { Signer } = require('@fastify/cookie');
243
243
 
244
- const signer = fastifyCookie.signerFactory('secret');
244
+ const signer = new Signer('secret');
245
245
  const signedValue = signer.sign('test');
246
246
  const {valid, renew, value } = signer.unsign(signedValue);
247
247
  ```
@@ -0,0 +1,18 @@
1
+ const Benchmark = require('benchmark')
2
+ const Signer = require('../signer')
3
+ const suite = new Benchmark.Suite()
4
+
5
+ const signer = Signer(['abcd', 'asdf', 'vadfa'])
6
+ const signedValue = signer.sign('test', 'vadfa')
7
+
8
+ suite
9
+ .add('sign', function () {
10
+ signer.sign('test')
11
+ })
12
+ .add('unsign', function () {
13
+ signer.unsign(signedValue)
14
+ })
15
+ .on('cycle', function (event) {
16
+ console.log(String(event.target))
17
+ })
18
+ .run({ delay: 0 })
@@ -0,0 +1,17 @@
1
+ const Benchmark = require('benchmark')
2
+ const Signer = require('../signer')
3
+ const suite = new Benchmark.Suite()
4
+
5
+ const signer = Signer('abcd')
6
+ const signedValue = signer.sign('test')
7
+ suite
8
+ .add('sign', function () {
9
+ signer.sign('test')
10
+ })
11
+ .add('unsign', function () {
12
+ signer.unsign(signedValue)
13
+ })
14
+ .on('cycle', function (event) {
15
+ console.log(String(event.target))
16
+ })
17
+ .run({ delay: 0 })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastify/cookie",
3
- "version": "7.3.1",
3
+ "version": "7.4.0",
4
4
  "description": "Plugin for fastify to add support for cookies",
5
5
  "main": "plugin.js",
6
6
  "types": "plugin.d.ts",
@@ -39,9 +39,10 @@
39
39
  },
40
40
  "homepage": "https://github.com/fastify/fastify-cookie#readme",
41
41
  "devDependencies": {
42
+ "@fastify/pre-commit": "^2.0.2",
42
43
  "@types/node": "^18.0.0",
44
+ "benchmark": "^2.1.4",
43
45
  "fastify": "^4.0.0-rc.2",
44
- "pre-commit": "^1.2.2",
45
46
  "sinon": "^14.0.0",
46
47
  "snazzy": "^9.0.0",
47
48
  "standard": "^17.0.0",
@@ -51,7 +52,6 @@
51
52
  },
52
53
  "dependencies": {
53
54
  "cookie": "^0.5.0",
54
- "cookie-signature": "^1.1.0",
55
55
  "fastify-plugin": "^4.0.0"
56
56
  },
57
57
  "tsd": {
package/plugin.d.ts CHANGED
@@ -8,11 +8,7 @@ declare module "fastify" {
8
8
  * Unsigns the specified cookie using the secret provided.
9
9
  * @param value Cookie value
10
10
  */
11
- unsignCookie(value: string): {
12
- valid: boolean;
13
- renew: boolean;
14
- value: string | null;
15
- };
11
+ unsignCookie(value: string): fastifyCookie.UnsignResult;
16
12
  /**
17
13
  * Manual cookie parsing method
18
14
  * @docs https://github.com/fastify/fastify-cookie#manual-cookie-parsing
@@ -39,11 +35,7 @@ declare module "fastify" {
39
35
  * Unsigns the specified cookie using the secret provided.
40
36
  * @param value Cookie value
41
37
  */
42
- unsignCookie(value: string): {
43
- valid: boolean;
44
- renew: boolean;
45
- value: string | null;
46
- };
38
+ unsignCookie(value: string): fastifyCookie.UnsignResult;
47
39
  }
48
40
 
49
41
  export type setCookieWrapper = (
@@ -89,11 +81,7 @@ declare module "fastify" {
89
81
  * Unsigns the specified cookie using the secret provided.
90
82
  * @param value Cookie value
91
83
  */
92
- unsignCookie(value: string): {
93
- valid: boolean;
94
- renew: boolean;
95
- value: string | null;
96
- };
84
+ unsignCookie(value: string): fastifyCookie.UnsignResult;
97
85
  }
98
86
  }
99
87
 
@@ -102,13 +90,15 @@ type FastifyCookiePlugin = FastifyPluginCallback<
102
90
  >;
103
91
 
104
92
  declare namespace fastifyCookie {
105
- export interface Signer {
106
- sign: (input: string) => string;
107
- unsign: (input: string) => {
108
- valid: boolean;
109
- renew: boolean;
110
- value: string | null;
111
- };
93
+ interface SignerBase {
94
+ sign: (value: string) => string;
95
+ unsign: (input: string) => UnsignResult;
96
+ }
97
+
98
+ export class Signer implements SignerBase {
99
+ constructor (secrets: string | Array<string>, algorithm?: string)
100
+ sign: (value: string) => string;
101
+ unsign: (input: string) => UnsignResult;
112
102
  }
113
103
 
114
104
  export interface CookieSerializeOptions {
@@ -129,9 +119,15 @@ declare namespace fastifyCookie {
129
119
  parseOptions?: fastifyCookie.CookieSerializeOptions;
130
120
  }
131
121
 
132
- export type Sign = (value: string, secret: string) => string;
133
- export type Unsign = (input: string, secret: string) => string | false;
134
- export type SignerFactory = (secret: string) => Signer;
122
+ export type Sign = (value: string, secret: string, algorithm?: string) => string;
123
+ export type Unsign = (input: string, secret: string, algorithm?: string) => UnsignResult;
124
+ export type SignerFactory = (secrets: string | Array<string>, algorithm?: string) => SignerBase;
125
+
126
+ export interface UnsignResult {
127
+ valid: boolean;
128
+ renew: boolean;
129
+ value: string | null;
130
+ }
135
131
 
136
132
  export const signerFactory: SignerFactory;
137
133
  export const sign: Sign;
@@ -139,6 +135,7 @@ declare namespace fastifyCookie {
139
135
 
140
136
  export interface FastifyCookie extends FastifyCookiePlugin {
141
137
  signerFactory: SignerFactory;
138
+ Signer: Signer;
142
139
  sign: Sign;
143
140
  unsign: Unsign;
144
141
  }
@@ -146,7 +143,8 @@ declare namespace fastifyCookie {
146
143
  export const fastifyCookie: FastifyCookie;
147
144
 
148
145
  export interface FastifyCookieOptions {
149
- secret?: string | string[] | Signer;
146
+ secret?: string | string[] | SignerBase;
147
+ algorithm?: string;
150
148
  parseOptions?: CookieSerializeOptions;
151
149
  }
152
150
 
@@ -157,4 +155,4 @@ declare function fastifyCookie(
157
155
  ...params: Parameters<FastifyCookiePlugin>
158
156
  ): ReturnType<FastifyCookiePlugin>;
159
157
 
160
- export = fastifyCookie;
158
+ export = fastifyCookie;
package/plugin.js CHANGED
@@ -1,10 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const { sign, unsign } = require('cookie-signature')
4
3
  const fp = require('fastify-plugin')
5
4
  const cookie = require('cookie')
6
5
 
7
- const signerFactory = require('./signer')
6
+ const { Signer, sign, unsign } = require('./signer')
8
7
 
9
8
  function fastifyCookieSetCookie (reply, name, value, options, signer) {
10
9
  const opts = Object.assign({}, options)
@@ -65,7 +64,8 @@ function onReqHandlerWrapper (fastify) {
65
64
  function plugin (fastify, options, next) {
66
65
  const secret = options.secret || ''
67
66
  const enableRotation = Array.isArray(secret)
68
- const signer = typeof secret === 'string' || enableRotation ? signerFactory(secret) : secret
67
+ const algorithm = options.algorithm || 'sha256'
68
+ const signer = typeof secret === 'string' || enableRotation ? new Signer(secret, algorithm) : secret
69
69
 
70
70
  fastify.decorate('parseCookie', parseCookie)
71
71
  fastify.decorate('signCookie', signCookie)
@@ -127,14 +127,17 @@ const fastifyCookie = fp(plugin, {
127
127
  * - `import { fastifyCookie } from 'fastify-cookie'`
128
128
  * - `import fastifyCookie from 'fastify-cookie'`
129
129
  */
130
+ fastifyCookie.signerFactory = Signer
130
131
  fastifyCookie.fastifyCookie = fastifyCookie
131
132
  fastifyCookie.default = fastifyCookie
132
133
  module.exports = fastifyCookie
133
134
 
134
- fastifyCookie.fastifyCookie.signerFactory = signerFactory
135
+ fastifyCookie.fastifyCookie.signerFactory = Signer
136
+ fastifyCookie.fastifyCookie.Signer = Signer
135
137
  fastifyCookie.fastifyCookie.sign = sign
136
138
  fastifyCookie.fastifyCookie.unsign = unsign
137
139
 
138
- module.exports.signerFactory = signerFactory
140
+ module.exports.signerFactory = Signer
141
+ module.exports.Signer = Signer
139
142
  module.exports.sign = sign
140
143
  module.exports.unsign = unsign
package/signer.js CHANGED
@@ -1,32 +1,116 @@
1
1
  'use strict'
2
2
 
3
- const cookieSignature = require('cookie-signature')
3
+ // Inspired by node-cookie-signature
4
+ // https://github.com/tj/node-cookie-signature
5
+ //
6
+ // The MIT License
7
+ // Copyright (c) 2012–2022 LearnBoost <tj@learnboost.com> and other contributors;
4
8
 
5
- module.exports = function (secret) {
6
- const secrets = Array.isArray(secret) ? secret : [secret]
7
- const [signingKey] = secrets
9
+ const crypto = require('crypto')
8
10
 
9
- return {
10
- sign (value) {
11
- return cookieSignature.sign(value, signingKey)
12
- },
13
- unsign (signedValue) {
14
- let valid = false
15
- let renew = false
16
- let value = null
17
-
18
- for (const key of secrets) {
19
- const result = cookieSignature.unsign(signedValue, key)
20
-
21
- if (result !== false) {
22
- valid = true
23
- renew = key !== signingKey
24
- value = result
25
- break
26
- }
27
- }
11
+ const base64PaddingRE = /=/g
12
+
13
+ function Signer (secrets, algorithm = 'sha256') {
14
+ if (!(this instanceof Signer)) {
15
+ return new Signer(secrets, algorithm)
16
+ }
28
17
 
29
- return { valid, renew, value }
18
+ this.secrets = Array.isArray(secrets) ? secrets : [secrets]
19
+ this.signingKey = this.secrets[0]
20
+ this.algorithm = algorithm
21
+
22
+ validateSecrets(this.secrets)
23
+ validateAlgorithm(this.algorithm)
24
+ }
25
+
26
+ function validateSecrets (secrets) {
27
+ for (const secret of secrets) {
28
+ if (typeof secret !== 'string') {
29
+ throw new TypeError('Secret key must be a string.')
30
30
  }
31
31
  }
32
32
  }
33
+
34
+ function validateAlgorithm (algorithm) {
35
+ // validate that the algorithm is supported by the node runtime
36
+ try {
37
+ crypto.createHmac(algorithm, 'dummyHmac')
38
+ } catch (e) {
39
+ throw new TypeError(`Algorithm ${algorithm} not supported.`)
40
+ }
41
+ }
42
+
43
+ function _sign (value, secret, algorithm) {
44
+ if (typeof value !== 'string') {
45
+ throw new TypeError('Cookie value must be provided as a string.')
46
+ }
47
+ return value + '.' + crypto
48
+ .createHmac(algorithm, secret)
49
+ .update(value)
50
+ .digest('base64')
51
+ // remove base64 padding (=) as it has special meaning in cookies
52
+ .replace(base64PaddingRE, '')
53
+ }
54
+
55
+ function _unsign (signedValue, secrets, algorithm) {
56
+ if (typeof signedValue !== 'string') {
57
+ throw new TypeError('Signed cookie string must be provided.')
58
+ }
59
+ const value = signedValue.slice(0, signedValue.lastIndexOf('.'))
60
+ const actual = Buffer.from(signedValue.slice(signedValue.lastIndexOf('.') + 1))
61
+
62
+ for (const secret of secrets) {
63
+ const expected = Buffer.from(crypto
64
+ .createHmac(algorithm, secret)
65
+ .update(value)
66
+ .digest('base64')
67
+ // remove base64 padding (=) as it has special meaning in cookies
68
+ .replace(base64PaddingRE, ''))
69
+ if (
70
+ expected.length === actual.length &&
71
+ crypto.timingSafeEqual(expected, actual)
72
+ ) {
73
+ return {
74
+ valid: true,
75
+ renew: secret !== secrets[0],
76
+ value
77
+ }
78
+ }
79
+ }
80
+
81
+ return {
82
+ valid: false,
83
+ renew: false,
84
+ value: null
85
+ }
86
+ }
87
+
88
+ Signer.prototype.sign = function (value) {
89
+ return _sign(value, this.signingKey, this.algorithm)
90
+ }
91
+
92
+ Signer.prototype.unsign = function (signedValue) {
93
+ return _unsign(signedValue, this.secrets, this.algorithm)
94
+ }
95
+
96
+ function sign (value, secret, algorithm = 'sha256') {
97
+ const secrets = Array.isArray(secret) ? secret : [secret]
98
+
99
+ validateSecrets(secrets)
100
+
101
+ return _sign(value, secrets[0], algorithm)
102
+ }
103
+
104
+ function unsign (signedValue, secret, algorithm = 'sha256') {
105
+ const secrets = Array.isArray(secret) ? secret : [secret]
106
+
107
+ validateSecrets(secrets)
108
+
109
+ return _unsign(signedValue, secrets, algorithm)
110
+ }
111
+
112
+ module.exports = Signer
113
+ module.exports.signerFactory = Signer
114
+ module.exports.Signer = Signer
115
+ module.exports.sign = sign
116
+ module.exports.unsign = unsign
@@ -4,7 +4,7 @@ const tap = require('tap')
4
4
  const test = tap.test
5
5
  const Fastify = require('fastify')
6
6
  const sinon = require('sinon')
7
- const cookieSignature = require('cookie-signature')
7
+ const { sign, unsign } = require('../signer')
8
8
  const plugin = require('../')
9
9
 
10
10
  test('cookies get set correctly', (t) => {
@@ -151,7 +151,7 @@ test('share options for setCookie and clearCookie', (t) => {
151
151
  const cookies = res.cookies
152
152
  t.equal(cookies.length, 2)
153
153
  t.equal(cookies[0].name, 'foo')
154
- t.equal(cookies[0].value, cookieSignature.sign('foo', secret))
154
+ t.equal(cookies[0].value, sign('foo', secret))
155
155
  t.equal(cookies[0].maxAge, 36000)
156
156
 
157
157
  t.equal(cookies[1].name, 'foo')
@@ -190,7 +190,7 @@ test('expires should not be overridden in clearCookie', (t) => {
190
190
  const cookies = res.cookies
191
191
  t.equal(cookies.length, 2)
192
192
  t.equal(cookies[0].name, 'foo')
193
- t.equal(cookies[0].value, cookieSignature.sign('foo', secret))
193
+ t.equal(cookies[0].value, sign('foo', secret))
194
194
  const expires = new Date(cookies[0].expires)
195
195
  t.ok(expires < new Date(Date.now() + 5000))
196
196
 
@@ -378,7 +378,7 @@ test('cookies signature', (t) => {
378
378
  const cookies = res.cookies
379
379
  t.equal(cookies.length, 1)
380
380
  t.equal(cookies[0].name, 'foo')
381
- t.equal(cookieSignature.unsign(cookies[0].value, secret), 'foo')
381
+ t.same(unsign(cookies[0].value, secret), { valid: true, renew: false, value: 'foo' })
382
382
  })
383
383
  })
384
384
 
@@ -406,7 +406,7 @@ test('cookies signature', (t) => {
406
406
  const cookies = res.cookies
407
407
  t.equal(cookies.length, 1)
408
408
  t.equal(cookies[0].name, 'foo')
409
- t.equal(cookieSignature.unsign(cookies[0].value, secret1), 'cookieVal') // decode using first key
409
+ t.same(unsign(cookies[0].value, secret1), { valid: true, renew: false, value: 'cookieVal' }) // decode using first key
410
410
  })
411
411
  })
412
412
 
@@ -427,7 +427,7 @@ test('cookies signature', (t) => {
427
427
  method: 'GET',
428
428
  url: '/test1',
429
429
  headers: {
430
- cookie: `foo=${cookieSignature.sign('foo', secret)}`
430
+ cookie: `foo=${sign('foo', secret)}`
431
431
  }
432
432
  }, (err, res) => {
433
433
  t.error(err)
@@ -452,7 +452,7 @@ test('cookies signature', (t) => {
452
452
  method: 'GET',
453
453
  url: '/test1',
454
454
  headers: {
455
- cookie: `foo=${cookieSignature.sign('foo', secret)}`
455
+ cookie: `foo=${sign('foo', secret)}`
456
456
  }
457
457
  }, (err, res) => {
458
458
  t.error(err)
@@ -477,7 +477,7 @@ test('cookies signature', (t) => {
477
477
  method: 'GET',
478
478
  url: '/test1',
479
479
  headers: {
480
- cookie: `foo=${cookieSignature.sign('foo', secret)}`
480
+ cookie: `foo=${sign('foo', secret)}`
481
481
  }
482
482
  }, (err, res) => {
483
483
  t.error(err)
@@ -503,7 +503,7 @@ test('cookies signature', (t) => {
503
503
  method: 'GET',
504
504
  url: '/test1',
505
505
  headers: {
506
- cookie: `foo=${cookieSignature.sign('foo', secret2)}`
506
+ cookie: `foo=${sign('foo', secret2)}`
507
507
  }
508
508
  }, (err, res) => {
509
509
  t.error(err)
@@ -529,7 +529,7 @@ test('cookies signature', (t) => {
529
529
  method: 'GET',
530
530
  url: '/test1',
531
531
  headers: {
532
- cookie: `foo=${cookieSignature.sign('foo', secret2)}`
532
+ cookie: `foo=${sign('foo', secret2)}`
533
533
  }
534
534
  }, (err, res) => {
535
535
  t.error(err)
@@ -555,7 +555,7 @@ test('cookies signature', (t) => {
555
555
  method: 'GET',
556
556
  url: '/test1',
557
557
  headers: {
558
- cookie: `foo=${cookieSignature.sign('foo', 'invalid-secret')}`
558
+ cookie: `foo=${sign('foo', 'invalid-secret')}`
559
559
  }
560
560
  }, (err, res) => {
561
561
  t.error(err)
@@ -581,7 +581,7 @@ test('cookies signature', (t) => {
581
581
  method: 'GET',
582
582
  url: '/test1',
583
583
  headers: {
584
- cookie: `foo=${cookieSignature.sign('foo', 'invalid-secret')}`
584
+ cookie: `foo=${sign('foo', 'invalid-secret')}`
585
585
  }
586
586
  }, (err, res) => {
587
587
  t.error(err)
@@ -109,6 +109,10 @@ const appWithImplicitHttpSigned = fastify();
109
109
  appWithImplicitHttpSigned.register(cookie, {
110
110
  secret: 'testsecret',
111
111
  });
112
+ appWithImplicitHttpSigned.register(cookie, {
113
+ secret: 'testsecret',
114
+ algorithm: 'sha512'
115
+ });
112
116
  appWithImplicitHttpSigned.after(() => {
113
117
  server.get('/', (request, reply) => {
114
118
  appWithImplicitHttpSigned.unsignCookie(request.cookies.test!);
@@ -194,3 +198,9 @@ appWithCustomSigner.after(() => {
194
198
  reply.send({ hello: 'world' })
195
199
  })
196
200
  })
201
+
202
+ new fastifyCookieStar.Signer('secretString')
203
+ new fastifyCookieStar.Signer(['secretStringInArray'])
204
+ const signer = new fastifyCookieStar.Signer(['secretStringInArray'], 'sha256')
205
+ signer.sign('Lorem Ipsum')
206
+ signer.unsign('Lorem Ipsum')
@@ -2,33 +2,67 @@
2
2
 
3
3
  const { test } = require('tap')
4
4
  const sinon = require('sinon')
5
- const cookieSignature = require('cookie-signature')
6
- const signerFactory = require('../signer')
5
+ const crypto = require('crypto')
6
+ const { Signer, sign, unsign } = require('../signer')
7
7
 
8
- test('default', (t) => {
9
- t.plan(2)
8
+ test('default', t => {
9
+ t.plan(5)
10
10
 
11
11
  const secret = 'my-secret'
12
- const signer = signerFactory(secret)
12
+ const signer = Signer(secret)
13
13
 
14
- t.test('signer.sign', (t) => {
14
+ t.test('signer.sign should throw if there is no value provided', (t) => {
15
15
  t.plan(1)
16
16
 
17
+ t.throws(() => signer.sign(undefined), 'Cookie value must be provided as a string.')
18
+ })
19
+
20
+ t.test('signer.sign', (t) => {
21
+ t.plan(2)
22
+
17
23
  const input = 'some-value'
18
24
  const result = signer.sign(input)
19
25
 
20
- t.equal(result, cookieSignature.sign(input, secret))
26
+ t.equal(result, sign(input, secret))
27
+ t.throws(() => sign(undefined), 'Cookie value must be provided as a string.')
21
28
  })
22
29
 
23
- t.test('signer.unsign', (t) => {
30
+ t.test('sign', (t) => {
24
31
  t.plan(3)
25
32
 
26
- const input = cookieSignature.sign('some-value', secret)
33
+ const input = 'some-value'
34
+ const result = signer.sign(input)
35
+
36
+ t.equal(result, sign(input, secret))
37
+ t.equal(result, sign(input, [secret]))
38
+
39
+ t.throws(() => sign(undefined), 'Cookie value must be provided as a string.')
40
+ })
41
+
42
+ t.test('signer.unsign', (t) => {
43
+ t.plan(4)
44
+
45
+ const input = signer.sign('some-value', secret)
27
46
  const result = signer.unsign(input)
28
47
 
29
48
  t.equal(result.valid, true)
30
49
  t.equal(result.renew, false)
31
50
  t.equal(result.value, 'some-value')
51
+ t.throws(() => signer.unsign(undefined), 'Signed cookie string must be provided.')
52
+ })
53
+
54
+ t.test('unsign', (t) => {
55
+ t.plan(6)
56
+
57
+ const input = sign('some-value', secret)
58
+ const result = unsign(input, secret)
59
+
60
+ t.equal(result.valid, true)
61
+ t.equal(result.renew, false)
62
+ t.equal(result.value, 'some-value')
63
+ t.same(result, unsign(input, [secret]))
64
+ t.throws(() => unsign(undefined), 'Secret key must be a string.')
65
+ t.throws(() => unsign(undefined, secret), 'Signed cookie string must be provided.')
32
66
  })
33
67
  })
34
68
 
@@ -37,11 +71,11 @@ test('key rotation', (t) => {
37
71
  const secret1 = 'my-secret-1'
38
72
  const secret2 = 'my-secret-2'
39
73
  const secret3 = 'my-secret-3'
40
- const signer = signerFactory([secret1, secret2, secret3])
41
- const unsignSpy = sinon.spy(cookieSignature, 'unsign')
74
+ const signer = Signer([secret1, secret2, secret3])
75
+ const signSpy = sinon.spy(crypto, 'createHmac')
42
76
 
43
77
  t.beforeEach(() => {
44
- unsignSpy.resetHistory()
78
+ signSpy.resetHistory()
45
79
  })
46
80
 
47
81
  t.test('signer.sign always signs using first key', (t) => {
@@ -50,30 +84,51 @@ test('key rotation', (t) => {
50
84
  const input = 'some-value'
51
85
  const result = signer.sign(input)
52
86
 
53
- t.equal(result, cookieSignature.sign(input, secret1))
87
+ t.equal(result, sign(input, secret1))
54
88
  })
55
89
 
56
90
  t.test('signer.unsign tries to decode using all keys till it finds', (t) => {
57
91
  t.plan(4)
58
92
 
59
- const input = cookieSignature.sign('some-value', secret2)
93
+ const input = sign('some-value', secret2)
94
+ signSpy.resetHistory()
60
95
  const result = signer.unsign(input)
61
96
 
62
97
  t.equal(result.valid, true)
63
98
  t.equal(result.renew, true)
64
99
  t.equal(result.value, 'some-value')
65
- t.equal(unsignSpy.callCount, 2) // should have returned early when the right key was found
100
+ t.equal(signSpy.callCount, 2) // should have returned early when the right key was found
66
101
  })
67
102
 
68
103
  t.test('signer.unsign failure response', (t) => {
69
104
  t.plan(4)
70
105
 
71
- const input = cookieSignature.sign('some-value', 'invalid-secret')
106
+ const input = sign('some-value', 'invalid-secret')
107
+ signSpy.resetHistory()
72
108
  const result = signer.unsign(input)
73
109
 
74
110
  t.equal(result.valid, false)
75
111
  t.equal(result.renew, false)
76
112
  t.equal(result.value, null)
77
- t.equal(unsignSpy.callCount, 3) // should have tried all 3
113
+ t.equal(signSpy.callCount, 3) // should have tried all 3
114
+ })
115
+ })
116
+
117
+ test('Signer', t => {
118
+ t.plan(2)
119
+
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.')
124
+ t.doesNotThrow(() => Signer('secret'))
125
+ t.doesNotThrow(() => Signer(['secret']))
126
+ })
127
+
128
+ t.test('Signer handles algorithm properly', (t) => {
129
+ t.plan(3)
130
+ t.throws(() => Signer('secret', 'invalid'), 'Algorithm invalid not supported.')
131
+ t.doesNotThrow(() => Signer('secret', 'sha512'))
132
+ t.doesNotThrow(() => Signer('secret', 'sha256'))
78
133
  })
79
134
  })