diff --git a/src/components/settings/SecurityTab.tsx b/src/components/settings/SecurityTab.tsx index 5413c482..154ecb4d 100644 --- a/src/components/settings/SecurityTab.tsx +++ b/src/components/settings/SecurityTab.tsx @@ -225,14 +225,7 @@ export function SecurityTab() { {hasPassword ? ( <>Update your password to keep your account secure. ) : ( - <> - Add password authentication to your account for increased security and backup access. - {identities.length > 0 && ( - - If you've previously set a password but don't see it here, click "Add Password" to re-verify your authentication. - - )} - + <>Add password authentication to your account for increased security and backup access. )} diff --git a/src/lib/identityService.ts b/src/lib/identityService.ts index f9bc6e62..6faa8e05 100644 --- a/src/lib/identityService.ts +++ b/src/lib/identityService.ts @@ -189,7 +189,7 @@ async function waitForEmailProvider(maxRetries = 6): Promise { /** * Add password authentication to an OAuth-only account - * Also handles re-creating email identity for orphaned passwords + * Automatically creates email identity by signing in immediately after setting password */ export async function addPasswordToAccount( password: string @@ -203,64 +203,70 @@ export async function addPasswordToAccount( }; } - // Update user with password (works for both new and existing passwords) - const { error } = await supabase.auth.updateUser({ password }); - - if (error) throw error; - - // Force session refresh to sync identity state - const { error: refreshError } = await supabase.auth.refreshSession(); - if (refreshError) { - console.warn('[IdentityService] Session refresh failed:', refreshError); + const { data: { user } } = await supabase.auth.getUser(); + if (!user?.email) { + return { + success: false, + error: 'No email address found on your account' + }; } - // Wait for email provider to be created - const emailCreated = await waitForEmailProvider(); + // Step 1: Update password + console.log('[IdentityService] Setting password for user'); + const { error: updateError } = await supabase.auth.updateUser({ password }); + if (updateError) throw updateError; - if (!emailCreated) { - // Password was set but identity verification failed - // Try one more aggressive approach: sign in with the new password - console.log('[IdentityService] Attempting sign-in to trigger identity creation'); + // Step 2: IMMEDIATELY attempt sign-in to force identity creation + // This is the ONLY reliable way to create the email identity + console.log('[IdentityService] Attempting sign-in to create email identity'); + const { error: signInError } = await supabase.auth.signInWithPassword({ + email: user.email, + password: password + }); + + if (signInError) { + // Sign-in failed, but password was set + console.error('[IdentityService] Sign-in failed:', signInError); - const { data: { user } } = await supabase.auth.getUser(); - if (user?.email) { - // Attempt to sign in (this might create the identity) - const { error: signInError } = await supabase.auth.signInWithPassword({ - email: user.email, - password: password - }); - - if (!signInError) { - // Sign-in successful, check identities again - const retriedEmailCreated = await waitForEmailProvider(2); // Quick retry - if (retriedEmailCreated) { - console.log('[IdentityService] Email provider created after sign-in'); - - // Log audit event - await logIdentityChange(user.id, 'password_added', { - method: 'oauth_fallback_with_signin_retry' - }); - - return { success: true }; - } + // Check if it's just an email confirmation issue + if (signInError.message?.includes('Email not confirmed')) { + // Password is set, identity might be created, just needs confirmation + console.log('[IdentityService] Email confirmation required, checking identity'); + const emailCreated = await waitForEmailProvider(3); + if (emailCreated) { + await logIdentityChange(user.id, 'password_added', { + method: 'oauth_fallback_unconfirmed' + }); + return { success: true }; } } return { success: false, - error: 'Password was set but email provider verification failed. Please refresh the page and try signing in with your email and password.' + error: `Password was set but authentication failed: ${signInError.message}. Please try signing out and signing back in with your email and password.` }; } - // Log audit event - const { data: { user } } = await supabase.auth.getUser(); - if (user) { - await logIdentityChange(user.id, 'password_added', { - method: 'oauth_fallback' - }); + // Step 3: Verify identity was created + console.log('[IdentityService] Sign-in successful, verifying identity creation'); + const emailCreated = await waitForEmailProvider(4); + + if (!emailCreated) { + console.error('[IdentityService] Identity not found after successful sign-in'); + return { + success: false, + error: 'Password authentication was successful but identity verification failed. Please refresh the page.' + }; } + // Step 4: Log success + console.log('[IdentityService] Email identity successfully created'); + await logIdentityChange(user.id, 'password_added', { + method: 'oauth_fallback_signin' + }); + return { success: true }; + } catch (error: any) { console.error('[IdentityService] Failed to add password:', error); return {