设置自定义声明后,Firestore 令牌不会在安全规则中更新



TLDR;

  1. 根据自定义声明设置消防仓库安全规则
  2. Cloud firestore用户是通过电话身份验证创建的
  3. 云功能在创建用户时触发,并添加一个自定义声明角色-admin。在实时数据库中更新条目以指示索赔更新
  4. 监听客户端中实时数据库的更新,并在更新自定义声明后调用user.getIdToken(true);
  5. 能够在代码中看到添加的自定义声明
  6. 由于缺少权限(自定义声明),无法读取firestore中的文档
  7. 刷新浏览器页面,现在可以阅读文档

我有一个云函数,它在用户创建时添加了一个自定义声明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安全调用。

最新更新