Verifying Email with Firebase.auth is not quite Reactive

Photo by Minh Pham on Unsplash

In the past year, I’ve been using Firebase quite a bit, and it became my exclusive backend since February at work, meaning I’ve been using it for personal projects quite a bit as well.

For the most part, I love what they’re doing, although writing security rules can be slightly unintuitive at first, and it’s also quite easy to fall into the trap of requesting too many reads when creating subscriptions.

But there’s one issue that’s caused me a fair bit of problems in the last few days:

Email Verification

So I ran into a couple of unexpected behaviours with this that I did not expect whatsoever, and I ended up wasting quite a few hours trying to figure out what the problems were. In summary, there were two behaviours on Firebase’s side that are quite unexpected (at least for noobs like me still deep-diving into this).

So just in case anyone else struggles with the same issues, I figured I’d write an article about the issue (because to be frank, I could not find much information about this).

1: Firebase auth does not push the change

Everything else in Firebase seems to be created around the concept of observable WebSockets, making it in particular easy to set up frontend observables with RxJs to make your web app reactive EVEN from the API layer!

Photo by Jaycee Xie on Unsplash

Expecting the same behavior from Firebase.auth when I verify email addresses, I struggled to understand why my frontend did not automtically redirect users into the protected part of the site as my redirect middleware was instructed to do.

Well turns out having email set to verified does not warrant a push on .onIdTokenChanged() subscriptions.

Fair enough, so I ended up with three possible solutions around this shortcoming:

  • Users have to refresh or open the site in a new window to refetch user data
  • Users prompt the site to fetch again (say, with a button)
  • While the user is in the situation of being told to verify, short-polling can continuously check and automatically update the situation

Perhaps there are better solutions, but viable ones for my web application seemed to be one of those three.

I ended up going with the first one for the time being and continued developing until I encountered the second unexpected behaviour.

2. Firebase.auth does not automatically issue new Id Tokens on change

So now it’s starting to get quite funky. I’m using .onIdTokenChanged() to subscribe for tokens, but a new token is not necessarily issued just because a user verifies their email.

Photo by Andre Tan on Unsplash

This one is far funkier than the earlier behaviour.

What happened would be the following:

The user verifies email and refreshes the site.

Upon refreshing, firebase.auth().onIdTokenChanged returns a user object, containing user fields including emailVerified and token.

The emailVerified field (which I use for frontend logic) is set to true.

However, when I decode the token, I see that it has emailVerified set to false.

Of course, this took me quite a bit of time to discover, as I naturally assumed the user object that I received from firebase.auth() would be identical to the object wrapped in the id token.

Wow, so silly. Much wrong.

So I(foolishly) assumed user.emailVerified is good enough, but I suddenly noticed requests failing when trying to alter fields protected by the following rule:

allow read, create, write: if request.auth != null && request.auth.token.email_verified == true;

So for this, there’s a couple of solutions, both of which are rather meh.

  • Force users to log out and in when verifying their email
  • Decode the user.token output of onIdTokenChanged(), check if token and user have different data, and if they do, request a new token manually by calling user.getIdToken(true)

For now, I ended up going with the second solution, though I’m not too happy about having to decode tokens in the frontend. I suppose I’m not sure exactly what I expected, since new tokens are only issued upon invalidation.

Photo by Christal Yuen on Unsplash

Conclusion

Perhaps my rant is unwarranted. In most authentication services I would expect this behaviour, but the other ways that Firebase makes data reactive in a completely seamless manner I was expecting authentication to work the same way.

Just be careful when implementing email verification! Things are not quite what they seem!

Web developer working in Tokyo. Passionate about clever RxJs usage and finding creative pipes to solve problems elegantly. Currently developing www.proxjs.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store