如何使自定义声明与Firebase数据库中存储的角色保持同步

时间:2019-01-28 00:54:53

标签: firebase firebase-authentication google-cloud-firestore firebase-security-rules

这个问题是从a comment on another thread提出的,我认为这是一个很好的问题,但尚无任何答案。

  

我如何将auth中的用户链接到他们在数据库中的特定配置文件? (配置文件包含全名,用户类型等)

问题的上下文是指将用户身份验证访问逻辑存储在数据库中和/或作为自定义声明的不同策略。以及如何保持这两个同步(Is there any function in User Authentication for User Roles?)。

1 个答案:

答案 0 :(得分:2)

必须使用admin SDK设置自定义声明,这已经暗示可以利用云功能来根据您的逻辑设置声明。

如果用户配置文件数据包含用户类型和角色,则可以创建触发器以更新用户对象。如果将角色存储为数组,则可以实现这样的功能。

functions.firestore.document('users/{uid}').onUpdate((change, context) => {
  const uid = context.params.uid;
  const userBefore = change.before.data();
  const userAfter = change.after.data();

  const hasDifferentNumberOfRoles = userBefore.roles.length !== userAfter.roles.length;
  const hasOtherRoles = userBefore.roles.some((role: string) => userAfter.roles.indexOf(role) === -1);

  if (hasDifferentNumberOfRoles || hasOtherRoles) {
    return admin.auth().setCustomUserClaims(uid, { appRoles: userAfter.roles});  
  }

  return null;
});

这可确保每次数据库中的用户角色更改时,您的自定义声明身份验证也将更改。

数组对于角色来说很方便,因为使用array-contains可以很容易地查询Firestore以查找具有某些角色的用户,也可以很容易地检查database rules as a list中的角色。

service cloud.firestore {
  match /databases/{database}/documents {

    match /protected-content/{documentId} {
      allow read: if hasUserRole('admin');
      allow write: if hasUserRole('super-admin');
    }

    function hasUserRole(role) {
      return role in request.auth.token.appRoles;
    }
  }
}

关于将角色存储在自定义声明的appRoles属性中的一个小注解是,如果您更改结构或想替换某个角色的所有角色,可以轻松方便地删除所有当前角色。用户。