From fb8e4ea741b71397aad44fbd60d6e5ba3de9542f Mon Sep 17 00:00:00 2001 From: kolaente Date: Thu, 2 Apr 2026 18:55:04 +0200 Subject: [PATCH] feat: add PKCE utility functions for OIDC auth Add generateCodeVerifier() and generateCodeChallenge() helpers that implement RFC 7636 PKCE using the Web Crypto API. Ref: #2410 --- frontend/src/helpers/pkce.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 frontend/src/helpers/pkce.ts diff --git a/frontend/src/helpers/pkce.ts b/frontend/src/helpers/pkce.ts new file mode 100644 index 000000000..e9bc0df18 --- /dev/null +++ b/frontend/src/helpers/pkce.ts @@ -0,0 +1,30 @@ +/** + * Generate a cryptographically random code_verifier (43-128 chars, RFC 7636 Section 4.1). + * Uses unreserved characters: [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" + */ +export function generateCodeVerifier(): string { + const array = new Uint8Array(32) + crypto.getRandomValues(array) + return base64UrlEncode(array) +} + +/** + * Compute code_challenge = BASE64URL(SHA256(code_verifier)) (RFC 7636 Section 4.2). + */ +export async function generateCodeChallenge(verifier: string): Promise { + const encoder = new TextEncoder() + const data = encoder.encode(verifier) + const digest = await crypto.subtle.digest('SHA-256', data) + return base64UrlEncode(new Uint8Array(digest)) +} + +function base64UrlEncode(bytes: Uint8Array): string { + let binary = '' + for (const byte of bytes) { + binary += String.fromCharCode(byte) + } + return btoa(binary) + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, '') +}