TLDR;
- 根据自定义声明设置消防仓库安全规则
- Cloud firestore用户是通过电话身份验证创建的
- 云功能在创建用户时触发,并添加一个自定义声明角色-admin。在实时数据库中更新条目以指示索赔更新
- 监听客户端中实时数据库的更新,并在更新自定义声明后调用
user.getIdToken(true);
- 能够在代码中看到添加的自定义声明
- 由于缺少权限(自定义声明),无法读取firestore中的文档
- 刷新浏览器页面,现在可以阅读文档
我有一个云函数,它在用户创建时添加了一个自定义声明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);
}
});
我对云消防商店有以下安全规则。
service cloud.firestore {
match /databases/{database}/documents {
match /{role}/{document=**} {
allow read: if request.auth != null &&
request.auth.token.role == role;
}
}
}
创建用户后,我的云函数会触发并添加自定义声明role = admin
。
由于user.getIdToken(true);
,令牌在我的客户端上被刷新,我可以看到设置的自定义声明。
当我试图获得用户应该能够阅读的文档时,我得到了云消防商店安全规则拒绝的权限。
当我刷新浏览器页面时,我可以读取路径中的文档。
我希望能够在不刷新浏览器的情况下访问firebase文档。这有可能吗?
有人能告诉我我的方法/期望有什么问题吗?
传播令牌的时间可能比您想象的要长。我广泛地使用自定义声明——我发现有效的方法是设置.onIdTokenChanged()
来跟踪uid&令牌更新,然后显式调用.getIdTokenResult(true)
来更新我的本地令牌。只有在两者都完成后,才能对Firestore和/或RTDB进行customClaim安全调用。