Skip to content

fix: pre-check Firestore para email cambio (Firebase Auth EEP silencia el error)#43

Merged
DevOtter97 merged 1 commit into
mainfrom
fix/email-change-pre-check
May 1, 2026
Merged

fix: pre-check Firestore para email cambio (Firebase Auth EEP silencia el error)#43
DevOtter97 merged 1 commit into
mainfrom
fix/email-change-pre-check

Conversation

@DevOtter97

Copy link
Copy Markdown
Owner

Bug reportado

Al intentar cambiar el email a uno ya registrado (en este caso una cuenta Gmail usada con Google sign-in):

  • La app dice "Te hemos enviado un email a [nuevo email], confírmalo desde ahí"
  • En realidad Firebase NO envia nada y NO lanza error
  • El usuario no sabe que ha fallado

Causa raiz

Firebase Email Enumeration Protection (EEP) esta activa por defecto en proyectos nuevos. Cuando lo esta:

  • verifyBeforeUpdateEmail(user, newEmail) con un email ya en uso devuelve success silencioso (no auth/email-already-in-use, no email enviado).
  • Razon de Firebase: prevenir que un atacante enumere cuentas registradas leyendo el codigo de error.

Mi codigo capturaba auth/email-already-in-use correctamente, pero Firebase nunca lo lanza estando EEP activa.

Fix (codigo)

Pre-check Firestore antes de llamar a Firebase:

  • src/infrastructure/firebase/FirestoreUserRepository.ts: nuevo metodo findUserIdByEmail(email) que hace query(users, where('email', '==', email), limit(1)). La regla users -> allow read: if auth != null ya permite la query y los campos single-field se auto-indexan, asi que sin cambios de reglas o indexes.
  • src/infrastructure/firebase/FirebaseAuthService.ts -> requestEmailChange: llama a findUserIdByEmail antes de verifyBeforeUpdateEmail. Si encuentra otro user con ese email, lanza Error('email-taken') para fail-fast con mensaje claro.
  • src/components/profile/AccountSecurityForm.tsx: el handler captura tanto message === 'email-taken' (nuestro pre-check) como code === 'auth/email-already-in-use' (Firebase post-EEP-disable) con el mismo mensaje "Ese email ya está en uso por otra cuenta".

Fix (Firebase Console — manual, fuera de codigo)

EEP tiene que estar OFF para cubrir el caso edge: usuarios que firmaron con Google y nunca completaron el perfil (existen en Firebase Auth pero NO en Firestore). El pre-check Firestore no los detecta. Con EEP off, Firebase Auth lanza auth/email-already-in-use y nuestro handler lo captura.

Pasos:

  1. Firebase Console -> proyecto gororeads -> Authentication -> Settings -> tab "User actions" (o "Configuración")
  2. Localizar "Email enumeration protection" -> toggle OFF -> Save

Trade-off: con EEP off, un atacante puede enumerar emails registrados (probar emails uno a uno y leer el codigo de error). Mitigado por el rate limit nativo de Firebase Auth. Para gororeads (tracker social pequeño) el riesgo es aceptable. Documentado en CLAUDE.md.

Cobertura del fix

Caso Pre-check Firestore Firebase Auth (EEP off)
Email de user con perfil Firestore ✅ detecta ✅ detecta
Email de user Google sin perfil completado ❌ no detecta ✅ detecta
Email totalmente disponible ✅ pasa ✅ envia mail

Las dos capas juntas cubren todos los casos.

Testing

  • npx astro check solo persiste el preexistente
  • npm run test:run 60/60
  • npm run build ok
  • Manual tras desactivar EEP: probar cambio a email de otro user con perfil -> "Ese email ya está en uso" inmediato (pre-check Firestore)
  • Manual: probar cambio a email de cuenta Google sin perfil -> "Ese email ya está en uso" tras la llamada a Firebase
  • Manual: probar cambio a email disponible -> recibir mail de confirmacion al nuevo address

Documentacion

CLAUDE.md -> seccion ## Notas de funcionamiento -> el bullet de cambio de email actualizado con la doble capa, y un bullet aparte con marca ⚠️ destacando que EEP debe estar OFF y por que.

@vercel

vercel Bot commented May 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gororeads Ready Ready Preview, Comment May 1, 2026 11:01pm

@DevOtter97 DevOtter97 merged commit 55c2b5b into main May 1, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant