Skip to content

Commit 5af2acf

Browse files
authored
@W-15248536@ - [v2] Google Search Console fix createCodeVerifier (#1765)
* Add entropy to nanoid createCodeVerifier * cleanup * bump main.js file size * Debug GA Windows builds * Set shell: true with spawnSync * Set shell: true with spawnSync on generator * lint * Update CHANGELOG.md * Add docs * Update CHANGELOG.md * Update CHANGELOG.md
1 parent 443f9fb commit 5af2acf

File tree

7 files changed

+81
-8
lines changed

7 files changed

+81
-8
lines changed

packages/pwa-kit-create-app/scripts/create-mobify-app-dev.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ const runGenerator = () => {
124124

125125
const extension = process.platform === 'win32' ? '.cmd' : ''
126126
const npm = `npm${extension}`
127-
const foundNpm = cp.spawnSync(npm, ['-v']).stdout.toString().trim()
127+
const foundNpm = cp.spawnSync(npm, ['-v'], {shell: true}).stdout.toString().trim()
128128
const flags = semver.satisfies(foundNpm, '>=7') ? '-y' : ''
129129

130130
const pathToNpxCache = p.join(sh.exec('npm config get cache', {silent: true}).trim(), '_npx')

packages/template-retail-react-app/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## v2.8.4 (May 2, 2024)
2+
3+
- Fixed createCodeVerifier adding entropy to be successfully indexed by Google Search Console. [#1765](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1765)
4+
- Fixed Node.js on Windows blocking spawSync .cmd unless { shell: true } is used with trusted code. [#1765](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1765)
5+
16
## v2.8.3 (Apr 9, 2024)
27

38
- Storefront Preview: avoid stale cached Commerce API responses, whenever the Shopper Context is set [#1740](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1740)

packages/template-retail-react-app/app/commerce-api/pkce.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,32 @@
44
* SPDX-License-Identifier: BSD-3-Clause
55
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
7-
import {nanoid} from 'nanoid'
7+
import {customRandom, urlAlphabet} from 'nanoid'
88
import {encode as base64encode} from 'base64-arraybuffer'
9+
import seedrandom from 'seedrandom'
910

1011
// Server Side
1112
const randomstring = require('randomstring')
1213

1314
// Globals
1415
const isServer = typeof window === 'undefined'
1516

17+
/**
18+
* Adds entropy to nanoid() using seedrandom to ensure that the code_challenge sent to SCAPI by Google's crawler browser is unique.
19+
* Solves the issue with Google's crawler getting the same result from nanoid() in two different runs, which results in the same PKCE code_challenge being used twice.
20+
*/
21+
const nanoid = () => {
22+
const rng = seedrandom(+new Date(), {entropy: true})
23+
return customRandom(urlAlphabet, 128, (size) => new Uint8Array(size).map(() => 256 * rng()))()
24+
}
25+
1626
/**
1727
* Creates Code Verifier use for PKCE auth flow.
1828
*
1929
* @returns {String} The 128 character length code verifier.
2030
*/
2131
export const createCodeVerifier = () => {
22-
return isServer ? randomstring.generate(128) : nanoid(128)
32+
return isServer ? randomstring.generate(128) : nanoid()
2333
}
2434

2535
/**
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2024, Salesforce, Inc.
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
import {createCodeVerifier, generateCodeChallenge} from './pkce'
8+
import seedrandom from 'seedrandom'
9+
10+
describe('PKCE Utility Functions', () => {
11+
describe('createCodeVerifier', () => {
12+
test('should generate unique code verifiers', () => {
13+
const verifiers = new Set()
14+
const numVerifiers = 100
15+
16+
for (let i = 0; i < numVerifiers; i++) {
17+
const verifier = createCodeVerifier()
18+
verifiers.add(verifier)
19+
}
20+
expect(verifiers.size).toBe(numVerifiers)
21+
})
22+
23+
test('should provide sufficient entropy', () => {
24+
const seed1 = 123456789
25+
const seed2 = 987654321
26+
seedrandom(seed1, {global: true})
27+
const verifier1 = createCodeVerifier()
28+
seedrandom(seed2, {global: true})
29+
const verifier2 = createCodeVerifier()
30+
// the generated verifiers should be different because we're using different seeds
31+
expect(verifier1).not.toBe(verifier2)
32+
})
33+
})
34+
35+
describe('generateCodeChallenge', () => {
36+
test('should generate a code challenge based on the provided code verifier', async () => {
37+
const codeVerifier = createCodeVerifier()
38+
const codeChallenge = await generateCodeChallenge(codeVerifier)
39+
40+
expect(codeChallenge).toBeDefined()
41+
})
42+
})
43+
})

packages/template-retail-react-app/package-lock.json

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/template-retail-react-app/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"react-helmet": "^6.1.0",
5353
"react-hook-form": "^6.15.8",
5454
"react-intl": "^5.25.1",
55-
"react-router-dom": "^5.3.4"
55+
"react-router-dom": "^5.3.4",
56+
"seedrandom": "^3.0.5"
5657
},
5758
"peerDependencies": {
5859
"@chakra-ui/system": "^1.12.1"
@@ -80,7 +81,7 @@
8081
"bundlesize": [
8182
{
8283
"path": "build/main.js",
83-
"maxSize": "55 kB"
84+
"maxSize": "56 kB"
8485
},
8586
{
8687
"path": "build/vendor.js",

scripts/check-version.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ const extension = isWin ? '.cmd' : ''
1313
const npm = `npm${extension}`
1414

1515
const spawnSync = (...args) => {
16-
const proc = childProc.spawnSync(...args)
16+
const proc = childProc.spawnSync(...args, { shell: true })
1717
if (proc.status !== 0) {
18-
throw proc.stderr.toString()
18+
console.error(proc)
19+
throw proc.stderr ? proc.stderr.toString() : 'Unknown error'
1920
}
2021
return proc
2122
}

0 commit comments

Comments
 (0)