Правила хранения Firebase с пользовательскими утверждениями - PullRequest
0 голосов
/ 27 февраля 2019

Мне не удается заставить Firebase Storage работать с настраиваемыми правилами и с использованием настраиваемых утверждений.

В моей панели администрирования Python я делаю следующее, чтобы создать пользователя и назначить утверждение client_id:

# Standard Auth
import firebase_admin
from firebase_admin import db, storage, auth
cred   = firebase_admin.credentials.Certificate('path_to_cert_json')
app    = firebase_admin.initialize_app(cred, 'config')
bucket = storage.bucket(app=app)

# Create User
auth.create_user(email=email) 

# Create custom claims
auth.set_custom_user_claims(uid, {'client_id': client_id})

Затем для правил Firebase я пытаюсь разрешить пользователю читать (или загружать) файлы только в том случае, если файл находится в подпапке с идентификатором client_id:

Структура файла в хранилище:

/{environment}/{client_id}/other_folders_and_files

Я установил следующие правила хранения:

service firebase.storage {
  match /b/{bucket}/o {
    match /{environment}/{client_id}/{allPaths=**} {
      allow read: if request.auth.token.client_id == client_id
    }
  }
}

Но это дает мне ошибку, что в доступе отказано.

Что я делаю не так?

Примечание:

  • client_id правильный и структура папок правильная, проверил это миллион раз.

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

Пользовательские заявки - единственный способ сделать это прямо сейчас.Правила должны выглядеть следующим образом:

service firebase.storage {
  match /b/{bucket}/o {
    function isAuth() {
      return request.auth != null && request.auth.uid != null
    }
    function isAdmin() {
      return isAuth() &&
      request.auth.token.admin == true;
    }
    function clientMatch(clientId) { // expects user's "client" field to be ID of client
      return isAuth() &&
      clientId == request.auth.token.clientId;
    }
    match /storage/path/{clientId}/{allPaths=**} {
        allow read, write: if isAdmin() || clientMatch(clientId)
    }

, где мы используем два пользовательских поля в токене аутентификации: admin и clientId.Облачная функция для синхронизации с базой данных может выглядеть примерно так:

exports.updateUser = functions.firestore
  .document('users/{userId}')
  .onWrite( async (change, context) => {
    // change.before and change.after are DocumentSnapshot objects
    const userid=context.params.userId // (from {userId} above)
    const isDeleted = !change.after.exists
    const isNew = !change.before.exists
    let customClaims = {}
    if (!isDeleted) {
      let newData = change.after.data()
      let oldData = change.before.data()
      // do we need to update anything?
      if (isNew ||
          newData.admin !== oldData.admin ||
          newData.client !== oldData.client) {
        customClaims.admin = Boolean(newData.admin)
        customClaims.clientId = newData.client
      }
    }
    else {
      let oldData = change.before.data()
      customClaims.admin = false
      customClaims.clientId = null
    }
    // now do the update if needed
    if (customClaims !== {}) {
      // See https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth
      await admin.auth().setCustomUserClaims(userid, customClaims)
      console.log(`Updating client for ${isNew?"new":"existing"} user ${userid}: ` +
                  `${JSON.stringify(customClaims)}`)
    }
  })

Она запускается при любых изменениях в пользовательском документе и синхронизирует ее с пользовательскими утверждениями автора.

0 голосов
/ 01 марта 2019

Если я не ошибаюсь, вы используете это неправильно.Должно быть:

service firebase.storage {
  match /b/{bucket}/o {
    match /{environment}/{client_id}/{allPaths=**} {
      allow read: if request.auth.uid == client_id
    }
  }
}

Токен возвращает другие объекты, например:

  • email
  • email_verified
  • phone_number
  • имя
  • sub

Так что вы можете сравнить идентификатор пользователя, который вы должны использовать request.auth.uid.Таким образом, будет сравниваться идентификатор клиента.Если вы хотите взглянуть на документы , это все о request.auth.

Edit

Если вам нужен ваш собственный токен, например: request.auth.token.client_id, вам нужно сделать это с помощью этого кода в Python:

uid = 'some-uid'
additional_claims = {
    'client_id': your_custom_client_id
}

custom_token = auth.create_custom_token(uid, additional_claims)

Тогда вы можете использовать в своих правилах хранения:

service firebase.storage {
  match /b/{bucket}/o {
    match /{environment}/{client_id}/{allPaths=**} {
      allow read: if request.auth.token.client_id == client_id
    }
  }
}

См. документы

...