From 286e5d467ddc9c0f5c393730ae9809db9730d1a0 Mon Sep 17 00:00:00 2001 From: Shreya Date: Thu, 3 Sep 2026 12:27:30 +0530 Subject: [PATCH] fix(auth): surface OIDC state errors instead of failing silently - When OIDC state handle is not found, callback now returns an Error instead of (null, undefined, undefined), which caused passport to fail silently with no feedback to the user or logs. - When OIDC state has expired, callback now returns a descriptive Error so the user gets a meaningful message instead of a silent redirect failure. - Replaced Math.random()-based handle generation with randomBytes(32) from node:crypto. The previous implementation was not cryptographically secure despite the comment claiming otherwise, making state handles potentially predictable. Fixes #7716 --- apps/api/src/app/auth/oidc-state.store.ts | 30 +++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/apps/api/src/app/auth/oidc-state.store.ts b/apps/api/src/app/auth/oidc-state.store.ts index aebd99892..b07598090 100644 --- a/apps/api/src/app/auth/oidc-state.store.ts +++ b/apps/api/src/app/auth/oidc-state.store.ts @@ -1,5 +1,6 @@ import type { Request } from 'express'; import ms from 'ms'; +import { randomBytes } from 'node:crypto'; // ADD THIS LINE import type { SessionStore, SessionStoreCallback, @@ -66,14 +67,21 @@ export class OidcStateStore implements SessionStore { const data = this.stateMap.get(handle); if (!data) { - return callback(null, undefined, undefined); - } + return callback( + new Error('Invalid OIDC state parameter'), + undefined, + undefined + ); +} - if (Date.now() - data.timestamp > this.STATE_EXPIRY_MS) { - // State has expired - this.stateMap.delete(handle); - return callback(null, undefined, undefined); - } +if (Date.now() - data.timestamp > this.STATE_EXPIRY_MS) { + this.stateMap.delete(handle); + return callback( + new Error('OIDC state has expired, please try again'), + undefined, + undefined + ); +} // Remove state after verification (one-time use) this.stateMap.delete(handle); @@ -106,10 +114,6 @@ export class OidcStateStore implements SessionStore { * Generate a cryptographically secure random handle */ private generateHandle() { - return ( - Math.random().toString(36).substring(2, 15) + - Math.random().toString(36).substring(2, 15) + - Date.now().toString(36) - ); - } + return randomBytes(32).toString('hex'); +} }