因此,我在firestore中有一个集合,该集合只能由已登录并经过验证的用户访问。
这是我保护它的方式:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function userIsAdmin() {
return request.auth.token.accessLevel >= 200;
}
function emailVerified() {
return request.auth.token.firebase.sign_in_provider != 'password'
|| request.auth.token.email_verified == true;
}
function isAuthed() {
return request.auth.uid != null && emailVerified(); // If I remove the && emailVerified() part, it works again in the frontend
}
function userIsSameAsResource(userId) {
return request.auth.uid == userId && emailVerified();
}
match /users/{userId} {
allow get: if isAuthed();
allow list: if userIsAdmin();
allow create, delete: if userIsAdmin();
allow update: if userIsAdmin()
|| userIsSameAsResource(userId);
}
}
}
使用规则模拟器可以按预期工作:
但是使用前端会发生这种情况:
Missing or insufficient permissions
以下是我的前端代码中的相关片段:
// currentAuthUserObs() is the current auth user from firebase (that part works)
// isEmailVerified() is described further down (works too)
// afStorage is AngularFire2's Firestore module
// 'HERE' and 'HERE2' are both printed, so that works as expected. The problem really is the query
this.auth.currentAuthUserObs().subscribe(async (authUser) => {
console.log('HERE');
if (authUser != null && await this.auth.emailAuth.isEmailVerified()) {
console.log('HERE2');
this.afStorage.doc(`${FirestoreCollections.USERS}/${authUser.uid}`).valueChanges()
.subscribe(user => {
console.log(user);
});
}
});
// In my case isEmailVerified gets called before and refreshes the currentUser, so it is ok to not call it with `refresh = true` in the subscription above.
public async isEmailVerified(refresh = false): Promise<boolean> {
if (refresh) {
await firebase.auth().currentUser.reload();
}
const isEmail = () => firebase.auth().currentUser.providerData.some(provider => provider.providerId == 'password');
return isEmail() ? firebase.auth().currentUser.emailVerified : true;
}
有人知道可能是什么问题吗?
答案 0 :(得分:0)
正如用户@Kato 所指出的,用户的 ID 令牌需要刷新。您可以使用 firebase.auth().currentUser.getIdToken(true)
来做到这一点 - 在我的示例中看起来像这样:
public async isEmailVerified(refresh = false): Promise<boolean> {
if (refresh) {
await firebase.auth().currentUser.reload();
await firebase.auth().currentUser.getIdToken(true); // <-- here
}
const isEmail = () => firebase.auth().currentUser.providerData.some(provider => provider.providerId == 'password');
return isEmail() ? firebase.auth().currentUser.emailVerified : true;
}