From da4f05adc35fcbc03fa4f283e045985f37c3af13 Mon Sep 17 00:00:00 2001 From: Wuesteon Date: Fri, 5 Dec 2025 04:26:34 +0100 Subject: [PATCH] fix(shared-auth): add UUID fallback for HTTP contexts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto.randomUUID() requires HTTPS (secure context). Staging uses HTTP, so add fallback using crypto.getRandomValues() which works in insecure contexts. Fallback chain: 1. crypto.randomUUID() - native, requires HTTPS 2. crypto.getRandomValues() - works on HTTP 3. Math.random() - last resort fallback 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- packages/shared-auth/src/adapters/device.ts | 38 ++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/shared-auth/src/adapters/device.ts b/packages/shared-auth/src/adapters/device.ts index c958dc1d1..a0c062297 100644 --- a/packages/shared-auth/src/adapters/device.ts +++ b/packages/shared-auth/src/adapters/device.ts @@ -2,6 +2,42 @@ import type { DeviceManagerAdapter, DeviceInfo } from '../types'; let deviceAdapter: DeviceManagerAdapter | null = null; +/** + * Generate a UUID with fallback for non-secure contexts (HTTP) + * crypto.randomUUID() requires HTTPS, so we fall back to crypto.getRandomValues() + */ +function generateUUID(): string { + // Try native randomUUID first (requires secure context) + if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') { + try { + return crypto.randomUUID(); + } catch { + // Falls through to fallback + } + } + + // Fallback: use crypto.getRandomValues() which works in insecure contexts + if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') { + const bytes = new Uint8Array(16); + crypto.getRandomValues(bytes); + + // Set version (4) and variant (RFC 4122) + bytes[6] = (bytes[6] & 0x0f) | 0x40; + bytes[8] = (bytes[8] & 0x3f) | 0x80; + + // Convert to hex string with dashes + const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join(''); + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; + } + + // Last resort: Math.random() based UUID (not cryptographically secure, but works) + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); +} + /** * Set the device manager adapter for the auth service */ @@ -37,7 +73,7 @@ export function createWebDeviceAdapter(): DeviceManagerAdapter { const storageKey = '@manacore/deviceId'; let deviceId = localStorage.getItem(storageKey); if (!deviceId) { - deviceId = crypto.randomUUID(); + deviceId = generateUUID(); localStorage.setItem(storageKey, deviceId); } return deviceId;