1

I have a Firebase cloud function to set custom claims on a Firebase user, found from given email.

This is the function code:

export const addAdmin = functions.https.onRequest(async (request, response) => {
  // Setting policies
  response.set("Access-Control-Allow-Origin", "*");
  response.set("Access-Control-Allow-Methods", "POST");
  response.set("Access-Control-Allow-Headers", "Content-Type");

  try {
    let details = JSON.parse(request.body);
    let user = await admin.auth().getUserByEmail(details.email);

    if (details.master !== "************") throw Error("Wrong Password");

    admin
      .auth()
      .setCustomUserClaims(user.uid, { admin: true })
      .then(() => {
        response.send(
          `User with uid ${user.uid} was set with claims - ${JSON.stringify(
            user.customClaims
          )}`
        );
      })
      .catch(error => {
        console.error(error);
        response.status(400).send(error);
      });
  } catch (error) {
    console.error(error);
    response.status(400).send(error);
  }
});

When i call this function from the client, I get the expected result:

User with uid JiT*******v0Pp7U2 was set with claims - {"admin":true}

but it doesn't seem to have set the claims. The security rules I set in Firestore is not recognizing the claims.

This is how my security rule is configured:

allow read: if request.auth.uid == userId || request.auth.token.admin == true;

I even tried logging the token.claims object on client side but that's also undefined

const token = await user?.getIdTokenResult();
console.log(token?.claims["admin"]);

What's going wrong here?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

6

Just refreshing the web page or re-running a query isn't enough to see a change to custom claims. In order for a user in a client app to see changes to their custom claims, the user has to either sign out and back in again, or force refresh their ID token with user.getIdToken(true).

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441