0
votes

I'm trying to implement custom claims in my Angular5(AngularFire2)/Cloud Firestore app with Firebase Auth. I want the following business rules to apply.

A cloud function updates all newly created firebase auth users from all sources(Google, email and password, Twitter, etc) to have custom claims set player is true and disabled is false.

    exports.processSignUpNewUser = functions.auth.user().onCreate(event => {
    const user = event.data; // The Firebase user.
    // Check if user meets role criteria.
    if (user.email &&
        user.emailVerified) {
      const customClaims = {
        player: true,
        disabled: false
      };
      // Set custom user claims on this newly created user.
      return admin.auth().setCustomUserClaims(user.uid, customClaims)
        .then(() => {
          // Update real-time database to notify client to force refresh.
          const metadataRef = admin.database().ref("metadata/" + user.uid);
          // Set the refresh time to the current UTC timestamp.
          // This will be captured on the client to force a token refresh.
          return metadataRef.set({refreshTime: new Date().getTime()});
        })
        .catch(error => {
          console.log(error);
        });
    }
  });

This function example from the Firebase docs does something for the realtime database that I'm not sure applies to Cloud Firestore. What do I have to do differently for Cloud Firestore?

I want another cloud function to update the user document role section for display purposes

exports.createUserAddDefaultRoles = functions.firestore
        .document('users/{userId}')
        .onCreate
        ((event) => {
        const data = event.data.data();

        const roles = '{ "disabled": false, "player": true }';

        return event.data.ref.set({
            roles: roles
        }, {merge: true});

How do I lock down the roles section of the user doc so only Cloud functions can update it and still allow the user to read the information on their profile and edit all the other properties of the user doc?
Is there a better function I could write to just update the roles section every time the user's custom claims change?

1

1 Answers

0
votes

Question 1: What the example does with the database is tell the client to refresh its authentication token so that the new claims work when making requests. Which basically means that when you update custom claims you have to tell the client to call firebase.auth().currentUser.getIdToken(true);.

Question 2: You can only control access to a specific document, not document properties, so my recommendation would be to create a different document collection for the stuff you don't want the user to edit. You need to update your firestore rules to:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userid}{
      allow read, write, update: if request.auth.uid == userid
    }
    match /userClaims/{userid}{
      allow read: if request.auth.uid == userid
    }
  }
}

Question 3: Since custom claims can only be changed on the server, make sure every time you change them, you also change the firestore doc either by calling a firestore function or doing it in the same code.

Sources: Firebase docs