'Firebase Auth: Unable to update custom claims after setting them with createCustomToken
Details
If you use the function createCustomToken to sign in the user and setting his custom claim, updating the custom claims later using the function setCustomUserClaims will not update the claims even after forcing the idToken to refresh using the function firebase.auth().currentUser.getIdTokenResult(true)
How to reproduce?
Sign in the user on firebase using a custom token generated with the function createCustomToken including the custom claims
firebase.auth().createCustomToken(uid, {myClaim: "test"}).then((customToken) => console.log(customToken))
Sign in the user on the frontend using the custom token
// copy paste the customToken manually for testing
firebase.auth().signInWithCustomToken(customToken)
Update the claim on the backend using setCustomUserClaims
firebase.auth().setCustomUserClaims(uid, {myClaim: "updateTest"})
Refresh the idToken on the frontEnd and log the custom claims
firebase.auth().currentUser
.getIdTokenResult(/*force refresh*/ true)
.then((idTokenResult) => {
console.log(`custom claims`, idTokenResult.claims)
})
You should see that the claim is still { myClaim: "test" } instead of { myClaim: "updateTest" }
Solution 1:[1]
Edit: This is actually an intended behavior. The claims set with createCustomToken have a higher priority. The doc mentions it here https://firebase.google.com/docs/auth/admin/custom-claims#set_and_validate_custom_user_claims_via_the_admin_sdk
Setting the custom claims separately at sign in instead of using the function createCustomToken to set them will allow you to edit these claims later.
Working code:
firestore
.doc(`users/${uid}`)
.get()
.then((clientSnapshot) => {
// give user the claims he has
const { permissions = {} } = clientSnapshot.data()
// use setCustomUserClaims to set the claims
return auth.setCustomUserClaims(uid, { permissions })
})
// generate the custom token
// ?? don't use createCustomToken to set permission as you won't be able to update them
.then(() => auth.createCustomToken(uid))
.then((customToken) => {
// send the custom token to the frontend to sign the user in
return res.status(200).json({ customToken })
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
