From b78c1c3c583a68644aab2aa69740937ce7776848 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Sat, 6 Jul 2024 17:23:10 +0800 Subject: [PATCH] fix: partitioned and autoChips should support different paths (#56) pick from https://github.com/eggjs/egg-cookies/pull/55 closes https://github.com/eggjs/egg-cookies/issues/53 --- lib/cookies.js | 25 +++++++++++++++++++++++-- test/lib/cookies.test.js | 31 +++++++++++++++++++++++++++++++ test/lib/keygrip.test.js | 3 +++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/lib/cookies.js b/lib/cookies.js index 309fe64..30d6748 100644 --- a/lib/cookies.js +++ b/lib/cookies.js @@ -163,7 +163,8 @@ class Cookies { // signed if (signed) { removeUnpartitionedCookie.name += '.sig'; - headers = ignoreCookiesByName(headers, removeUnpartitionedCookie.name); + headers = ignoreCookiesByNameAndPath(headers, + removeUnpartitionedCookie.name, removeUnpartitionedCookie.attrs.path); headers = pushCookie(headers, removeUnpartitionedCookie); } } else if (autoChips) { @@ -181,7 +182,8 @@ class Cookies { if (signed) { newPartitionedCookie.value = value && this.keys.sign(newPartitionedCookie.toString()); newPartitionedCookie.name += '.sig'; - headers = ignoreCookiesByName(headers, newPartitionedCookie.name); + headers = ignoreCookiesByNameAndPath(headers, + newPartitionedCookie.name, newPartitionedCookie.attrs.path); headers = pushCookie(headers, newPartitionedCookie); } } @@ -271,5 +273,24 @@ function ignoreCookiesByName(cookies, name) { return cookies.filter(c => !c.startsWith(prefix)); } +function ignoreCookiesByNameAndPath(cookies, name, path) { + if (!path) { + return ignoreCookiesByName(cookies, name); + } + const prefix = `${name}=`; + // foo=hello; path=/path1; samesite=none + const includedPath = `; path=${path};`; + // foo=hello; path=/path1 + const endsWithPath = `; path=${path}`; + return cookies.filter(c => { + if (c.startsWith(prefix)) { + if (c.includes(includedPath) || c.endsWith(endsWithPath)) { + return false; + } + } + return true; + }); +} + Cookies.CookieError = CookieError; module.exports = Cookies; diff --git a/test/lib/cookies.test.js b/test/lib/cookies.test.js index 8c6dbec..cb7e6c9 100644 --- a/test/lib/cookies.test.js +++ b/test/lib/cookies.test.js @@ -850,6 +850,37 @@ describe('test/lib/cookies.test.js', () => { } }); + it('should ignore remove unpartitioned property with different paths', () => { + const cookies = Cookies({ + secure: true, + headers: { + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.3945.29 Safari/537.36', + }, + }, { secure: true }, { autoChips: true, partitioned: false, removeUnpartitioned: true, sameSite: 'None' }); + const opts = { + signed: 1, + }; + cookies.set('foo', 'hello', opts); + cookies.set('foo', 'hello', { + signed: 1, + path: '/path2', + }); + + assert(opts.signed === 1); + assert(opts.secure === undefined); + const headers = cookies.ctx.response.headers['set-cookie']; + assert.deepEqual(headers, [ + '_CHIPS-foo=hello; path=/; samesite=none; secure; httponly; partitioned', + '_CHIPS-foo.sig=G4Idm9Wdp_vfCnUbOpQG284o22SgTe88SUmG6QW1ylk; path=/; samesite=none; secure; httponly; partitioned', + 'foo=hello; path=/; samesite=none; secure; httponly', + 'foo.sig=ZWbaA4bWk8ByBuYVgfmJ2DMvhhS3sOctMbfXAQ2vnwI; path=/; samesite=none; secure; httponly', + '_CHIPS-foo=hello; path=/path2; samesite=none; secure; httponly; partitioned', + '_CHIPS-foo.sig=G4Idm9Wdp_vfCnUbOpQG284o22SgTe88SUmG6QW1ylk; path=/path2; samesite=none; secure; httponly; partitioned', + 'foo=hello; path=/path2; samesite=none; secure; httponly', + 'foo.sig=ZWbaA4bWk8ByBuYVgfmJ2DMvhhS3sOctMbfXAQ2vnwI; path=/path2; samesite=none; secure; httponly', + ]); + }); + it('should disable autoChips when partitioned=true', () => { const cookies = Cookies({ secure: true, diff --git a/test/lib/keygrip.test.js b/test/lib/keygrip.test.js index 18e85b1..9272924 100644 --- a/test/lib/keygrip.test.js +++ b/test/lib/keygrip.test.js @@ -33,6 +33,9 @@ describe('test/lib/keygrip.test.js', () => { }); it('should decrypt key encrypted by createCipher without error', () => { + if (!crypto.createCipher) { + return; + } const keygrip = new Keygrip([ 'foo' ]); const encrypted = keygrip.encrypt('hello');