From bbf415e9f93dd38ea79e2534bea9acd95f681be2 Mon Sep 17 00:00:00 2001 From: Marcus Olsson <8396880+marcusolsson@users.noreply.github.com> Date: Thu, 21 May 2026 11:56:31 +0200 Subject: [PATCH] chore: use Web Crypto API for PKCE random generation --- src/plugin/pkce-flow.test.ts | 12 ++++++++++++ src/plugin/pkce-flow.ts | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/plugin/pkce-flow.test.ts b/src/plugin/pkce-flow.test.ts index 0050932..5672838 100644 --- a/src/plugin/pkce-flow.test.ts +++ b/src/plugin/pkce-flow.test.ts @@ -266,3 +266,15 @@ describe('exchangeCodeForTokens - Issue #3', () => { if (result.type !== 'failed') throw new Error('expected failed'); }); }); + +describe('generateCodeVerifier - Issue #10', () => { + it('produces a base64url string of the correct length (32 bytes => 43 chars)', async () => { + const mod = await import('./pkce-flow'); + const verifier = mod.generateCodeVerifier(); + + expect(typeof verifier).toBe('string'); + expect(verifier.length).toBe(43); // ceil(32 / 3) * 4 = 43 with base64url padding stripped + // base64url characters only + expect(verifier).toMatch(/^[A-Za-z0-9_-]+$/); + }); +}); diff --git a/src/plugin/pkce-flow.ts b/src/plugin/pkce-flow.ts index 2435f52..31ce4ce 100644 --- a/src/plugin/pkce-flow.ts +++ b/src/plugin/pkce-flow.ts @@ -238,7 +238,7 @@ async function executePkceAuthorization( // Generate PKCE parameters const codeVerifier = generateCodeVerifier(); const codeChallenge = generateCodeChallenge(codeVerifier); - const state = crypto.randomBytes(16).toString('hex'); + const state = generateRandomHex(16); const redirectUri = `http://localhost:${PKCE_CALLBACK_PORT}/callback`; // Build authorization URL @@ -279,11 +279,22 @@ function generateCodeChallenge(verifier: string): string { return crypto.createHash('sha256').update(verifier).digest('base64url'); } +/** + * Generate a random hex string using Web Crypto (non-blocking, idiomatic in Node 18+) + */ +function generateRandomHex(byteLength: number): string { + const bytes = new Uint8Array(byteLength); + crypto.webcrypto.getRandomValues(bytes); + return Buffer.from(bytes).toString('hex'); +} + /** * Generate a random string for PKCE code_verifier */ -function generateCodeVerifier(): string { - return crypto.randomBytes(32).toString('base64url'); +export function generateCodeVerifier(): string { + const bytes = new Uint8Array(32); + crypto.webcrypto.getRandomValues(bytes); + return Buffer.from(bytes).toString('base64url'); } /**