From 3e8edd188a1e6a7f0634982beee1d1259ed78d37 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Sun, 8 Feb 2026 21:36:42 +0100 Subject: [PATCH] fix: fetch full user profile after login in auth callback and welcome page to ensure correct display name --- app/auth/callback/page.tsx | 20 +++++++++++++++++--- app/welcome/page.tsx | 19 ++++++++++++++++--- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/app/auth/callback/page.tsx b/app/auth/callback/page.tsx index 631d19e..4891587 100644 --- a/app/auth/callback/page.tsx +++ b/app/auth/callback/page.tsx @@ -3,7 +3,7 @@ import { useEffect, useState, Suspense, useRef, useCallback } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import { useAuth } from '@/lib/auth/context' -import { AUTH_URL } from '@/lib/api/client' +import { AUTH_URL, default as apiRequest } from '@/lib/api/client' import { exchangeAuthCode, setSessionAction } from '@/app/actions/auth' import { authMessageFromErrorType, type AuthErrorType } from '@/lib/utils/authErrors' import { LoadingOverlay } from '@ciphera-net/ui' @@ -23,7 +23,14 @@ function AuthCallbackContent() { if (!code || !codeVerifier) return const result = await exchangeAuthCode(code, codeVerifier, redirectUri) if (result.success && result.user) { - login(result.user) + // * Fetch full profile (including display_name) before navigating so header shows correct name on first paint + try { + const fullProfile = await apiRequest<{ id: string; email: string; display_name?: string; totp_enabled: boolean; org_id?: string; role?: string }>('/auth/user/me') + const merged = { ...fullProfile, org_id: result.user.org_id ?? fullProfile.org_id, role: result.user.role ?? fullProfile.role } + login(merged) + } catch { + login(result.user) + } localStorage.removeItem('oauth_state') localStorage.removeItem('oauth_code_verifier') if (localStorage.getItem('pulse_pending_checkout')) { @@ -51,7 +58,14 @@ function AuthCallbackContent() { const handleDirectTokens = async () => { const result = await setSessionAction(token, refreshToken) if (result.success && result.user) { - login(result.user) + // * Fetch full profile (including display_name) before navigating so header shows correct name on first paint + try { + const fullProfile = await apiRequest<{ id: string; email: string; display_name?: string; totp_enabled: boolean; org_id?: string; role?: string }>('/auth/user/me') + const merged = { ...fullProfile, org_id: result.user.org_id ?? fullProfile.org_id, role: result.user.role ?? fullProfile.role } + login(merged) + } catch { + login(result.user) + } if (typeof window !== 'undefined' && localStorage.getItem('pulse_pending_checkout')) { router.push('/welcome') } else { diff --git a/app/welcome/page.tsx b/app/welcome/page.tsx index 1c3f64f..c16dff5 100644 --- a/app/welcome/page.tsx +++ b/app/welcome/page.tsx @@ -20,6 +20,7 @@ import { createCheckoutSession } from '@/lib/api/billing' import { createSite, type Site } from '@/lib/api/sites' import { setSessionAction } from '@/app/actions/auth' import { useAuth } from '@/lib/auth/context' +import apiRequest from '@/lib/api/client' import { getAuthErrorMessage } from '@/lib/utils/authErrors' import { trackWelcomeStepView, @@ -147,13 +148,19 @@ function WelcomeContent() { const { access_token } = await switchContext(org.organization_id) const result = await setSessionAction(access_token) if (result.success && result.user) { - login(result.user) + try { + const fullProfile = await apiRequest<{ id: string; email: string; display_name?: string; totp_enabled: boolean; org_id?: string; role?: string }>('/auth/user/me') + const merged = { ...fullProfile, org_id: result.user.org_id ?? fullProfile.org_id, role: result.user.role ?? fullProfile.role } + login(merged) + } catch { + login(result.user) + } router.refresh() trackWelcomeWorkspaceSelected() setStep(3) } } catch (err) { - toast.error(getAuthErrorMessage(err) || 'Failed to switch workspace') + toast.error(getAuthErrorMessage(err) || 'Failed to switch organization') } finally { setSwitchingOrgId(null) } @@ -178,7 +185,13 @@ function WelcomeContent() { const { access_token } = await switchContext(org.id) const result = await setSessionAction(access_token) if (result.success && result.user) { - login(result.user) + try { + const fullProfile = await apiRequest<{ id: string; email: string; display_name?: string; totp_enabled: boolean; org_id?: string; role?: string }>('/auth/user/me') + const merged = { ...fullProfile, org_id: result.user.org_id ?? fullProfile.org_id, role: result.user.role ?? fullProfile.role } + login(merged) + } catch { + login(result.user) + } router.refresh() } trackWelcomeWorkspaceCreated(!!(typeof window !== 'undefined' && localStorage.getItem('pulse_pending_checkout')))