From 7ffd1de2afefc6cd05fc560d4d680b006b5a1bd9 Mon Sep 17 00:00:00 2001 From: Brion Date: Tue, 15 Jul 2025 13:30:45 +0530 Subject: [PATCH 1/3] feat: enhance OAuth handling with improved error logging and state management --- .../contexts/Asgardeo/AsgardeoProvider.tsx | 38 ++++++++++--------- .../actions/handleOAuthCallbackAction.ts | 22 +++++++---- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/packages/nextjs/src/client/contexts/Asgardeo/AsgardeoProvider.tsx b/packages/nextjs/src/client/contexts/Asgardeo/AsgardeoProvider.tsx index a99e03a2..2946ea7a 100644 --- a/packages/nextjs/src/client/contexts/Asgardeo/AsgardeoProvider.tsx +++ b/packages/nextjs/src/client/contexts/Asgardeo/AsgardeoProvider.tsx @@ -119,10 +119,22 @@ const AsgardeoClientProvider: FC> // Handle OAuth callback automatically useEffect(() => { + // React 18.x Strict.Mode has a new check for `Ensuring reusable state` to facilitate an upcoming react feature. + // https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state + // This will remount all the useEffects to ensure that there are no unexpected side effects. + // When react remounts the signIn hook of the AuthProvider, it will cause a race condition. Hence, we have to + // prevent the re-render of this hook as suggested in the following discussion. + // https://github.com/reactwg/react-18/discussions/18#discussioncomment-795623 + if (reRenderCheckRef.current) { + return; + } + + reRenderCheckRef.current = true; + // Don't handle callback if already signed in if (isSignedIn) return; - const processOAuthCallback = async () => { + (async () => { try { const code = searchParams.get('code'); const state = searchParams.get('state'); @@ -132,13 +144,8 @@ const AsgardeoClientProvider: FC> // Check for OAuth errors first if (error) { - console.error('[AsgardeoClientProvider] OAuth error:', error, errorDescription); - // Redirect to sign-in page with error - router.push( - `/signin?error=${encodeURIComponent(error)}&error_description=${encodeURIComponent( - errorDescription || '', - )}`, - ); + logger.error('[AsgardeoClientProvider] An error was received for the initiated sign-in request.'); + return; } @@ -157,21 +164,16 @@ const AsgardeoClientProvider: FC> window.location.reload(); } } else { - router.push( - `/signin?error=authentication_failed&error_description=${encodeURIComponent( - result.error || 'Authentication failed', - )}`, + logger.error( + `[AsgardeoClientProvider] An error occurred while signing in: ${result.error || 'Authentication failed'}`, ); } } } catch (error) { - console.error('[AsgardeoClientProvider] Failed to handle OAuth callback:', error); - router.push('/signin?error=authentication_failed'); + logger.error('[AsgardeoClientProvider] Failed to handle OAuth callback:', error); } - }; - - processOAuthCallback(); - }, [searchParams, router, isSignedIn, handleOAuthCallback]); + })(); + }, []); useEffect(() => { if (!preferences?.theme?.mode || preferences.theme.mode === 'system') { diff --git a/packages/nextjs/src/server/actions/handleOAuthCallbackAction.ts b/packages/nextjs/src/server/actions/handleOAuthCallbackAction.ts index ecaf364d..bef27970 100644 --- a/packages/nextjs/src/server/actions/handleOAuthCallbackAction.ts +++ b/packages/nextjs/src/server/actions/handleOAuthCallbackAction.ts @@ -21,6 +21,7 @@ import {cookies} from 'next/headers'; import AsgardeoNextClient from '../../AsgardeoNextClient'; import SessionManager from '../../utils/SessionManager'; +import logger from '../../utils/logger'; /** * Server action to handle OAuth callback with authorization code. @@ -68,11 +69,15 @@ const handleOAuthCallbackAction = async ( const tempSession = await SessionManager.verifyTempSession(tempSessionToken); sessionId = tempSession.sessionId; } catch { - // TODO: Invalid temp session, throw error. + logger.error( + '[handleOAuthCallbackAction] Invalid temporary session token, falling back to session ID from cookies.', + ); } } if (!sessionId) { + logger.error('[handleOAuthCallbackAction] No session ID found in cookies or temporary session token.'); + return { success: false, error: 'No session found. Please start the authentication flow again.', @@ -92,10 +97,13 @@ const handleOAuthCallbackAction = async ( if (signInResult) { try { - const idToken = await asgardeoClient.getDecodedIdToken(sessionId); - const accessToken: string = signInResult['access_token']; + const idToken = await asgardeoClient.getDecodedIdToken( + sessionId, + signInResult['id_token'] || signInResult['idToken'], + ); + const accessToken: string = signInResult['accessToken'] || signInResult['access_token']; const userIdFromToken = idToken.sub || signInResult['sub'] || sessionId; - const scopes = idToken['scope'] ? idToken['scope'].split(' ') : []; + const scopes = signInResult['scope']; const organizationId = idToken['user_org'] || idToken['organization_id']; const sessionToken = await SessionManager.createSessionToken( @@ -110,9 +118,9 @@ const handleOAuthCallbackAction = async ( cookieStore.delete(SessionManager.getTempSessionCookieName()); } catch (error) { - console.warn( - '[handleOAuthCallbackAction] Failed to create JWT session, continuing with legacy session:', - error, + logger.error( + `[handleOAuthCallbackAction] Failed to create JWT session, continuing with legacy session: + ${typeof error === 'string' ? error : JSON.stringify(error)}`, ); } } From 8b505db09e35d18e97ff0dddf995fc3bfaf1c06f Mon Sep 17 00:00:00 2001 From: Brion Date: Tue, 15 Jul 2025 13:32:39 +0530 Subject: [PATCH 2/3] fix: change logger level from error to debug for improved logging --- packages/nextjs/src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/nextjs/src/index.ts b/packages/nextjs/src/index.ts index b6d37266..ff673b41 100644 --- a/packages/nextjs/src/index.ts +++ b/packages/nextjs/src/index.ts @@ -18,5 +18,8 @@ export {default as AsgardeoNext} from './AsgardeoNextClient'; +// TODO: Remove this export once the docs are live. +export * from './server'; + // @asgardeo/nextjs exports. export * from './client'; From 593f5d442f4a1ffc937e1831aaadf455464e28d0 Mon Sep 17 00:00:00 2001 From: Brion Date: Tue, 15 Jul 2025 13:33:53 +0530 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20add=20changeset=20=F0=9F=A6=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/six-spiders-say.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/six-spiders-say.md diff --git a/.changeset/six-spiders-say.md b/.changeset/six-spiders-say.md new file mode 100644 index 00000000..9e62ba33 --- /dev/null +++ b/.changeset/six-spiders-say.md @@ -0,0 +1,5 @@ +--- +'@asgardeo/nextjs': patch +--- + +Enhance OAuth handling with improved error logging and state management