Правила Firestore не допускают претензий для пользователя signInWithCustomToken, использующего пользовательский JWT - PullRequest
0 голосов
/ 20 июня 2019

У меня есть структурированный набор правил Firestore, что все работает отлично, за исключением пользовательских утверждений пользователя в пользовательском JWT.

Я использую фреймворк Laravel и kreait / firebase-php с createCustomToken вот так:

'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();
}

Правила пожарной охраны:

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
        )
    }
  }
}

EDIT

Вот код JavaScript, который записывает в документ system/config:

Замечание : Если я уберу проверку записи из правила 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 Ответ

1 голос
/ 20 июня 2019

Ваше правило для местоположения системы / конфигурации таково:

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 для проверки.

...