1

I'm making an app with Flutter and Firebase but I'm having issues with the "email_verified" check in Firebase Rules. I want to grant read access to documents only if the user has their email verified. The code seems to be correct, but when I create an account in my app and verify my email, I get a permission-denied error when trying to access the data in the documents. I'm only able to read the data if I sign out and in again. Therefore, I'm pretty sure the problem is that the auth token isn't being updated.

I saw some questions about this (like this one Firebase firestore not updating email verification status) but I wasn't able to apply the solution to my code, since I'm using Flutter and I wasn't able to find how to do that there.

Here's the Firebase Rules code that is failing:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /posts_data/{postId} {
      allow read: if request.auth.token.email_verified;
    }
  }
}

I'm not experienced with Firebase, so I would appreciate it if someone could tell me how exactly to force the auth token to update in Flutter.

David A.
  • 291
  • 1
  • 2
  • 7
  • Did you try force refreshing the token as mentioned in the linked answer? Where do you redirect user after email verification? – Dharmaraj Jan 16 '23 at 07:11
  • I redirect to the home page that shows all posts by accessing the very document that I'm trying to allow read in my question (so the home page reads /posts_data/{postId}). I'm getting syntax errors. Honestly, it's probably a very stupid mistake on my part due to my lack of knowledge/experience with Firebase Rules. I don't know where to place the code mentioned in the answer I linked. Where should I place Auth.auth().currentUser?.getIDTokenForcingRefresh(true) ? – David A. Jan 16 '23 at 07:19
  • 1
    That should run once right after user is redirected to your app after verifying their email. Then any requests after that will have verified email in token. Maybe you can add a param `?refresh=true` to your redirect URL and if its true, run that block of code. – Dharmaraj Jan 16 '23 at 07:21
  • Thanks for the comments, Dharmaraj. I think the issue is that I don't know how to write that in Flutter. I tried looking in the documentation for how to do that but couldn't find it. I just updated my question to better explain what I need. – David A. Jan 16 '23 at 07:36
  • 1
    In flutter we reload like this I think: `FirebaseAuth.instance.currentUser().then((user) { user.reload(); });` got this from this [docs](https://pub.dev/documentation/firebase_auth/latest/firebase_auth/User-class.html) there is a method called user.reload(); – Rohit Kharche Jan 16 '23 at 10:01
  • Wow, I feel so dumb. I was close, but it was like this in the end: AuthService().auth.currentUser?.getIdToken(true); Thank you for the help! – David A. Jan 16 '23 at 11:42

1 Answers1

1

You can force the token to update in Flutter by calling the reload() method on the FirebaseUser object after the email verification is complete. Try the following code after email verification done:

FirebaseAuth.instance.currentUser().then((user) async {
  await user.reload();
});

This will update the user's Auth token with the latest information from the Firebase server, including the email verification status.

OR

You can directly use user.isEmailVerified() when you try to access the unauthorized content just for debugging purposes.And you can also use FirebaseAuth.instance.currentUser().getIdToken() to get the auth token and verify that as well here's the reference for that.

Source: firebase_auth package

Rohit Kharche
  • 2,541
  • 1
  • 2
  • 13
  • 2
    Adding to this, its a good idea to force refresh token only when needed, in this case after user is redirected back to app after email verification. – Dharmaraj Jan 16 '23 at 16:08