Permissions problem with user on first login

230 views
Skip to first unread message

michael griffith

unread,
Sep 11, 2020, 8:03:52 PM9/11/20
to Firebase Google Group

Using Firebase Firestore (V2.0 rules)

When registering a user in my application I am creating a custom claim and passing an id to the token to ensure the user can only read/write data to collections where they are a group participant. 

An example looks like:

match /questionnaire/{questionnaireId}{

  allow read, get, list: if request.auth.token.participantId in resource.data.participants || isAdmin()
  allow create, update: if isAdmin();
  allow delete: if false;

}

 IsAdmin is a custom claim where {admin:true} and the other custom claim is set when the participant registers with the application,  I am setting a participantId as a custom claim on their user token.  So it looks like
{participantId : 1234} 

The rules work, I have hundreds of unit tests that prove they do.  When the user registers, I send email verification to their email account provided and they have to verify their email before they can login.  

Once in a while when the user tries to login for the first time, they receive a permission denied error on one or more of the collections.  Then if they clear caches and login the user is allowed to proceed without error. 

Is there a local copy of the rules in the browser cache that could be causing this very hard to replicate (but very important) error? 

It seems to happen frequently when creating new users and logging them in the first time.  Something that will probably never happen IRL but happens enough during our UAT testing that its raising client’s eyebrows.

Any/all replies appreciated. 

 MG

Sam Stern

unread,
Sep 14, 2020, 7:12:35 AM9/14/20
to Firebase Google Group
Hi Michael,

Rules are only ever evaluated server-side, the browser SDKs have no concept of rules and definitely don't have a rules cache.  Is it possible this is a simple race condition in your code? Maybe your code is trying to access Firesrtore before the sign-in operation has finished committing the latest ID token to the local session cache?

It's best practice to use an auth state listener as the source of truth for sign-in state:

So even after a successful client-side sign in operation, you should wait until the auth state changed listener fires before using the auth state (by accessing the DB, etc).  Hope that helps!

- Sam

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/89189d7f-818e-456a-bfc0-97b74ef19486n%40googlegroups.com.

michael griffith

unread,
Sep 14, 2020, 11:23:45 AM9/14/20
to Firebase Google Group
Sam, 

Thanks for the reply.  We are definitely using the auth state changed before trying to retrieve data.  Is it possible that the custom claim takes some time before being propagated to the token?  This problem seems to only present itself when the user tries to login for the first time.

Sam Stern

unread,
Sep 14, 2020, 11:42:07 AM9/14/20
to Firebase Google Group
Hi Michael,

How are you adding your custom claims?  If you're adding them as part of creating a custom auth token then there is no propagation. However if you're first creating the user through some other method (email/password, Google auth, Facebook auth, etc) and then adding custom claims using the Admin SDK there is some propagation delay.  Specifically the user will not have their custom claims until their client-side id token expires and the SDK automatically refreshes it. Client SDK tokens are refreshed every hour, so this could take up to one hour.


- Sam

michael griffith

unread,
Sep 17, 2020, 9:47:44 PM9/17/20
to fireba...@googlegroups.com
So I think I am in compliance with the spec.  The custom claim is created via a call on to the ADMIN SDK on the initial creation of the user. 

Specifically the spec reads:

After new claims are modified on a user via the Admin SDK, they are propagated to an authenticated user on the client side via the ID token in the following ways:

A user signs in or re-authenticates after the custom claims are modified. The ID token issued as a result will contain the latest claims.
An existing user session gets its ID token refreshed after an older token expires.
An ID token is force refreshed by calling currentUser.getIdToken(true).

Our registration process is something like this:
secondaryApp.auth().createUserWithEmailAndPassword(user.userName, user.password)
.then(result => {
uid = result.user.uid;
currentUser = secondaryApp.auth().currentUser;
...
const fbFunctions = secondaryApp.functions();
const setParticpantId = fbFunctions.httpsCallable('setParticpantId');
setParticpantId({email: currentUser.userName}).then(function (result) {
    secondaryApp.auth().signOut();
}).catch((err) => {
    secondaryApp.auth().signOut();
})
...
});
The user is also forced to validate their email address before they can use the app. 
If they try to login before their email address has been validated we warn them and log them out.
By the time they actually login, it is my understanding the token they get at that time should contain
the custom claim, as it was set during the resolve promise of the createUserWithEmailAndPassWord api call.
Does this seem correct?


Sam Stern

unread,
Sep 18, 2020, 6:03:59 AM9/18/20
to Firebase Google Group
Ok so if I am understanding correctly:
  • On the client you call createUserWithEmailAndPassword
  • Then you call a Callable Cloud Function setParticipantId()
  • On the server, inside the function, you set some custom claims
  • Then you sign out on the client
If all that is true then yes, by the time the user next signs in I would expect all custom claims to propagate. If not, that's a bug.  Can you reproduce this reliably or you're only getting sporadic customer reports?

- Sam

michael griffith

unread,
Sep 18, 2020, 5:52:29 PM9/18/20
to fireba...@googlegroups.com
Sam, you have the sequence down exactly.  We only see the permission error very sporadically.   We are in the process of trying to set up some automated tests to see if we can produce the error more reliably or with some indicator as to what might be causing the issue.

Sam Stern

unread,
Sep 21, 2020, 5:55:02 AM9/21/20
to Firebase Google Group
Thanks for confirming!  If you find a way to reproduce the problem or get some detailed logs, please file a bug on our firebase-js-sdk GitHub repository as that's likely the best starting point for this issue (although if it's a backend issue they'll move it).

- Sam

Reply all
Reply to author
Forward
0 new messages