From 1ec737f819dfc10de4108cd87dc0b386b9df0a8c Mon Sep 17 00:00:00 2001 From: Vaibhav <117663341+7ttp@users.noreply.github.com> Date: Sun, 9 Nov 2025 16:07:54 +0530 Subject: [PATCH] fix(auth-js): replace Math.random with crypto based UUID to support Next.js 16 SSR Next.js 16 App Router requires deterministic rendering for Server Components. The previous implementation of uuid() in @supabase/auth-js used Math.random(), which caused prerender errors even when no queries were executed. This update replaces Math.random() with crypto.getRandomValues in browsers and crypto.randomFillSync in Node, providing SSR-safe, fully synchronous UUID v4 generation. ### Changes - Refactored uuid() in packages/auth-js/src/lib/helpers.ts - Fully synchronous and UUID v4 compliant - Compatible with Node 16+ and modern browsers - Resolves SSR/deterministic rendering errors caused by Math.random() Closes #40273 --- packages/core/auth-js/src/lib/helpers.ts | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/core/auth-js/src/lib/helpers.ts b/packages/core/auth-js/src/lib/helpers.ts index 132839ab1..93987e96c 100644 --- a/packages/core/auth-js/src/lib/helpers.ts +++ b/packages/core/auth-js/src/lib/helpers.ts @@ -9,12 +9,24 @@ export function expiresAt(expiresIn: number) { return timeNow + expiresIn } -export function uuid() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - const r = (Math.random() * 16) | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8 - return v.toString(16) - }) +export function uuid(): string { + const bytes = new Uint8Array(16) + if (typeof crypto !== 'undefined' && crypto.getRandomValues) { + crypto.getRandomValues(bytes) + } else { + const cryptoNode = require('crypto') + cryptoNode.randomFillSync(bytes) + } + bytes[6] = (bytes[6] & 0x0f) | 0x40 + bytes[8] = (bytes[8] & 0x3f) | 0x80 + + let i = 0 + return bytes.reduce((uuid, byte) => { + const hex = byte.toString(16).padStart(2, '0') + if (i === 4 || i === 6 || i === 8 || i === 10) uuid += '-' + i++ + return uuid + hex + }, '') } export const isBrowser = () => typeof window !== 'undefined' && typeof document !== 'undefined'