From a70f7aca07c6d3c7b42c0a9487de2edf5cee0a43 Mon Sep 17 00:00:00 2001 From: IanShaw027 Date: Tue, 21 Apr 2026 01:05:59 +0800 Subject: [PATCH] fix pending auth session restore --- frontend/src/stores/__tests__/auth.spec.ts | 29 ++++++++++++++++++++++ frontend/src/stores/auth.ts | 24 +++++++++++------- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/frontend/src/stores/__tests__/auth.spec.ts b/frontend/src/stores/__tests__/auth.spec.ts index c96a606a..56195b5b 100644 --- a/frontend/src/stores/__tests__/auth.spec.ts +++ b/frontend/src/stores/__tests__/auth.spec.ts @@ -261,6 +261,35 @@ describe('useAuthStore', () => { expect(localStorage.getItem('pending_auth_session')).toBeNull() }) + it('restores a persisted pending oauth session without requiring a token value', () => { + const firstStore = useAuthStore() + + firstStore.setPendingAuthSession({ + token: '', + token_field: 'pending_oauth_token', + provider: 'oidc', + redirect: '/welcome', + adoption_required: true, + suggested_display_name: 'OIDC Nick' + }) + + setActivePinia(createPinia()) + const restoredStore = useAuthStore() + restoredStore.checkAuth() + + expect(restoredStore.isAuthenticated).toBe(false) + expect(restoredStore.hasPendingAuthSession).toBe(true) + expect(restoredStore.pendingAuthSession).toEqual({ + token: '', + token_field: 'pending_oauth_token', + provider: 'oidc', + redirect: '/welcome', + adoption_required: true, + suggested_display_name: 'OIDC Nick', + suggested_avatar_url: undefined + }) + }) + it('preserves pending auth session when registration fails', async () => { const store = useAuthStore() store.setPendingAuthSession({ diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts index 08ba5484..4b712692 100644 --- a/frontend/src/stores/auth.ts +++ b/frontend/src/stores/auth.ts @@ -28,6 +28,10 @@ interface PendingAuthSessionSummary { suggested_avatar_url?: string } +function normalizePendingAuthTokenField(value: unknown): PendingAuthTokenField { + return value === 'pending_oauth_token' ? 'pending_oauth_token' : 'pending_auth_token' +} + function getPersistedPendingAuthSession(): PendingAuthSessionSummary | null { const raw = localStorage.getItem(PENDING_AUTH_SESSION_KEY) if (!raw) { @@ -35,18 +39,20 @@ function getPersistedPendingAuthSession(): PendingAuthSessionSummary | null { } try { - const parsed = JSON.parse(raw) as PendingAuthSessionSummary - if (!parsed?.token || !parsed?.provider) { + const parsed = JSON.parse(raw) as Partial | null + const provider = typeof parsed?.provider === 'string' ? parsed.provider.trim() : '' + if (!provider) { + localStorage.removeItem(PENDING_AUTH_SESSION_KEY) return null } return { - token: parsed.token, - token_field: parsed.token_field || 'pending_auth_token', - provider: parsed.provider, - redirect: parsed.redirect, - adoption_required: parsed.adoption_required, - suggested_display_name: parsed.suggested_display_name, - suggested_avatar_url: parsed.suggested_avatar_url + token: typeof parsed?.token === 'string' ? parsed.token : '', + token_field: normalizePendingAuthTokenField(parsed?.token_field), + provider, + redirect: typeof parsed?.redirect === 'string' ? parsed.redirect : undefined, + adoption_required: typeof parsed?.adoption_required === 'boolean' ? parsed.adoption_required : undefined, + suggested_display_name: typeof parsed?.suggested_display_name === 'string' ? parsed.suggested_display_name : undefined, + suggested_avatar_url: typeof parsed?.suggested_avatar_url === 'string' ? parsed.suggested_avatar_url : undefined } } catch { localStorage.removeItem(PENDING_AUTH_SESSION_KEY)