Firestore规则不允许使用自定义JWT向signInWithCustomToken用户声明版权

时间:2019-06-20 13:19:06

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

我有一套结构化的Firestore规则,除了自定义JWT中的自定义用户声明外,其他所有功能都正常运行。

我正在使用Laravel框架,将kreait/firebase-phpcreateCustomToken一起使用,

'firebase_custom_token' => (string)$firebase->getAuth()->createCustomToken(
  "mrp-admin-user:{$user->id}", [
    'isPanel' => true,
    'userRoles' => $user->roleIds // returns an array like ['admin', 'operator']
  ]
)

然后在客户端,我就可以像这样成功登录Firebase:

firebase.auth().signInWithCustomToken(firebase_custom_token);

我有一个Firestore规则功能,该功能通过检查isPanel == true令牌声明来检查用户是否为面板用户:

function isPanelUser() {
  return request.auth != null && 
    'isPanel' in request.auth.token && 
    request.auth.token.isPanel == true
}

使用该功能的所有操作都会失败,并出现缺少权限或权限不足错误:

match /users/{userId}/{document=**} {
  allow read, write: if isSignedInAs(userId) || isPanelUser();
}

match /system/services/{serviceId}/{document=**} {
  allow read;
  allow write: if isPanelAdmin();
}

Firestore规则:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /system/config {
      allow read;
      allow write: if isPanelAdmin();
    }

    match /services/{serviceId}/{document=**} {
      allow read;
      allow write: if isPanelAdmin();
    }

    match /orders/{orderId}/{document=**} {
      allow read, write: if  isPanelUser() || isSignedInAs(resource.data.uid);
    }

    match /users/{userId}/{document=**} {
      allow read, write: if isSignedInAs(userId) || isPanelUser();
    }

    match /drivers/{userId}/{document=**} {
      allow read, write: if isSignedInAs(userId) || isPanelUser();
    }

    function isSignedIn() {
      return request.auth != null
    }

    function isSignedInAs(uid) {
      return request.auth != null && request.auth.uid == uid
    }

    function isPanelUser() {
      return request.auth != null && 
        'isPanel' in request.auth.token && 
        request.auth.token.isPanel == true
    }

    function isPanelUserOfRole(role) {
      return isPanelUser() == true && 
        'userRoles' in request.auth.token && 
        role in request.auth.token.userRoles
    }

    function isPanelSuperAdmin() {
      return isPanelUser() == true && 
        'userRoles' in request.auth.token && 
        'super-admin' in request.auth.token.userRoles
    }

    function isPanelAdmin() {
      return isPanelUser() == true && 
        'userRoles' in request.auth.token && (
          'admin' in request.auth.token.userRoles || 
          'super-admin' in request.auth.token.userRoles
        )
    }

    function isPanelOperator() {
      return isPanelUser() == true && 
        'userRoles' in request.auth.token && (
          'operator' in request.auth.token.userRoles ||
          'admin' in request.auth.token.userRoles || 
          'super-admin' in request.auth.token.userRoles
        )
    }
  }
}

编辑

这是写入system/config文档的javascript代码:

通知:如果我从system/config规则中删除了写检查,那么它将起作用并写入文档。

import firebase from "firebase/app";
import 'firebase/firestore';

...

const systemConfigRef = firebase.firestore().collection('system').doc('config');

systemConfigRef.set({
  status: 'down'
})
.then(docRef => {
  console.log('System config written');
})
.catch(error => {
  console.log('System config error', error); // getting permissions error
});

1 个答案:

答案 0 :(得分:1)

您的系统/配置位置规则是:

match /system/config {
  allow read;
  allow write: if isPanelAdmin();
}

您要求用户是panelAdmin,这比不仅仅是面板用户有更严格的要求:

function isPanelAdmin() {
      return isPanelUser() == true && 
      'userRoles' in request.auth.token && (
        'admin' in request.auth.token.userRoles || 
        'super-admin' in request.auth.token.userRoles
      )
    }

您既需要将userRoles数组放置在令牌上,又需要在该数组中包含“ admin”或“ super-admin”。您绝对确定

'userRoles' => $user->roleIds

以管理员或超级管理员返回数组?我建议将规则切换为仅调用isPanelUser而不是isPanelAdmin进行测试。