← Back to list

The Firebase Auth Edge Case That Broke My App for 1,200 Users (And the One-Line Fix)

Why checking emailVerified in authStateChanges leaves verified users stuck on the verification screen, and the one call that fixes it.

Ali Wajdan in Easy Flutter · 2026-05-09 10:01 · 2 claps · 2.2 min read
#flutter #firebase #authentication #mobile-app-development #software-engineering
Open on Medium ↗
Wiki topics: 📱 · Mobile Development

Why checking emailVerified in authStateChanges leaves verified users stuck on the verification screen, and the one call that fixes it.

Why checking emailVerified in authStateChanges leaves verified users stuck on the verification screen, and the one call that fixes it.

The Firebase Auth Edge Case That Broke My App for 1,200 Users (And the One-Line Fix)

Why checking emailVerified in authStateChanges leaves verified users stuck on the verification screen, and the one call that fixes it.

After a signup push that brought in over a thousand new users in a day, I started getting support tickets with a consistent complaint: users had clicked the verification link in their email and the app still wouldn’t let them through. They were stuck on the “please verify your email” screen.

I could see their accounts in the Firebase console. Email verified: true. But the app was telling them otherwise.

The bug was in how I was checking the email verification status.

My onboarding flow listened to authStateChanges and checked currentUser.emailVerified to decide whether to show the home screen or the verification screen. That logic seems correct. The problem is that Firebase Auth caches the user object locally. When the user clicks the verification link in their email, Firebase updates the verification status on the server, but the cached User object in the app doesn’t know about it yet. authStateChanges doesn’t fire again just because the email was verified. The local object is stale.

// This looks correct but uses stale cached data
FirebaseAuth.instance.authStateChanges().listen((user) {
  if (user == null) {
    navigateToLogin();
  } else if (!user.emailVerified) {
    navigateToVerification(); // User gets stuck here forever
  } else {
    navigateToHome();
  }
});

The verification screen had a “I’ve verified my email” button that re-checked the status. That button called FirebaseAuth.instance.currentUser?.reload() before checking emailVerified. That button worked correctly.

The issue was that users weren’t tapping it. They expected the app to detect the verification automatically. Some were tapping the verification link from inside the app’s email client, switching back, and finding themselves still blocked. Reasonable expectation. Broken behavior.

The fix is one call: reload the user before checking the verification status. reload() fetches the latest user data from Firebase’s servers and updates the local cached object.

// Check the current auth state, refreshing user data first
Future<void> checkAuthAndNavigate() async {
  final user = FirebaseAuth.instance.currentUser;

  if (user == null) {
    navigateToLogin();
    return;
  }

  // Reload forces a fresh fetch from Firebase — clears the stale cache
  await user.reload();

  // Now read from the updated object
  final refreshedUser = FirebaseAuth.instance.currentUser;

  if (refreshedUser?.emailVerified == true) {
    navigateToHome();
  } else {
    navigateToVerification();
  }

Call user.reload() before checking emailVerified anywhere in your auth flow. On the verification screen itself, poll every few seconds and call reload() each time. The moment the user verifies, the next reload() will reflect it and the navigation will trigger automatically. No “I’ve verified” button required.

The same pattern applies whenever you need a fresh copy of any Firebase user property: displayName, photoURL, phone number. The cached User object can be hours old. reload() is the only way to guarantee you’re reading the current state.

AUTHOR BIO Ali Wajdan is a Senior Mobile Engineer with 5+ years of experience shipping apps used by people across iOS and Android. I build cross-platform mobile apps, AI-integrated backends, and everything in between.

Portfolio: https://aliwajdan.com LinkedIn: https://www.linkedin.com/in/aliwajdanpasha GitHub: https://github.com/aliwajdan453


메타데이터
post_id
2d771df2e800
slug
the-firebase-auth-edge-case-that-broke-my-app-for-1-200-users-and-the-one-line-fix-2d771df2e800
url
https://medium.com/easy-flutter/the-firebase-auth-edge-case-that-broke-my-app-for-1-200-users-and-the-one-line-fix-2d771df2e800
canonical_url
https://medium.com/easy-flutter/the-firebase-auth-edge-case-that-broke-my-app-for-1-200-users-and-the-one-line-fix-2d771df2e800
author_url
https://medium.com/@aliwajdan
status
ok
fetched_at
2026-06-11 16:11:38