Firebase Firestore代币不';设置自定义声明后,无法更新安全规则
TLDRFirebase Firestore代币不';设置自定义声明后,无法更新安全规则,firebase,google-cloud-firestore,firebase-security,Firebase,Google Cloud Firestore,Firebase Security,TLDR 基于自定义声明设置firestore安全规则 云firestore用户由电话验证创建 云函数在创建用户时触发,并添加一个自定义声明角色-admin。实时数据库中会更新一个条目,以指示索赔更新 监听客户端中实时数据库的更新,并调用user.getIdToken(true)更新自定义索赔后 能够在代码中看到添加的自定义声明 由于缺少权限(自定义声明),无法读取firestore中的文档 刷新浏览器页面,现在可以读取文档 我有一个云函数,可以在用户创建时添加自定义声明role-admin
user.getIdToken(true)代码>更新自定义索赔后
我有一个云函数,可以在用户创建时添加自定义声明
role-admin
exports.processSignUp = functions.auth.user().onCreate((user) => {
const customClaims = {
role: 'admin',
};
// 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);
});
});
我监听实时数据库中的更改事件,以检测用户自定义声明的更新
let callback = null;
let metadataRef = null;
firebase.auth().onAuthStateChanged(user => {
// Remove previous listener.
if (callback) {
metadataRef.off('value', callback);
}
// On user login add new listener.
if (user) {
// Check if refresh is required.
metadataRef = firebase.database().ref('metadata/' + user.uid + '/refreshTime');
callback = (snapshot) => {
// Force refresh to pick up the latest custom claims changes.
// Note this is always triggered on first call. Further optimization could be
// added to avoid the initial trigger when the token is issued and already contains
// the latest claims.
user.getIdToken(true);
};
// Subscribe new listener to changes on that node.
metadataRef.on('value', callback);
}
});
我在云firestore上有以下安全规则
service cloud.firestore {
match /databases/{database}/documents {
match /{role}/{document=**} {
allow read: if request.auth != null &&
request.auth.token.role == role;
}
}
}
创建用户后,my cloud函数触发并添加自定义声明role=admin
作为user.getIdToken(true)的结果代码>在我的客户端上刷新令牌,我可以看到设置的自定义声明
当我试图获取用户应该能够阅读的文档时,我获得了被云firestore安全规则拒绝的权限
刷新浏览器页面时,我可以读取路径中的文档
我希望能够在不刷新浏览器的情况下访问firebase文档。这有可能吗
有人能告诉我我的方法/期望有什么问题吗?传播令牌的时间可能比您想象的要长。我广泛使用自定义声明-我发现有效的方法是设置.onIdTokenChanged()
来跟踪uid和令牌更新,然后显式调用.getIdTokenResult(true)
来更新我的本地令牌。只有在两者都完成后,您才能对Firestore和/或RTDB进行customClaim安全调用。我将添加-Firestore最近有一些更新似乎直接解决了这一问题。我没有尝试过它们,因为这里的解决方案对我有效。很遗憾,在我的情况下,收听onIdTokenChanged()
并调用。getIdTokenResult(true)
不起作用。我在.getIdTokenResult(true)中看到声明,然后
,但当我尝试读取.getIdTokenResult(true)中的文档时,仍然会出现缺少或权限不足
错误。然后
。