Firebase Storage Rules with Custom Claims

一个人想着一个人 提交于 2019-12-19 10:17:16

问题


I am unable to get Firebase Storage work with custom rules and using custom claims.

In my Python Admin panel, I do the following to create the user and assign a claim 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})

Then for Firebase rules, I try to allow the user to only read (or download) files when the file is in a subfolder with the client_id:

File structure on storage:

/{environment}/{client_id}/other_folders_and_files

I set the following storage rules:

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

But that gives me an error that Permission is denied.

What am I doing wrong?

Note:

  • client_id is correct and the folder structure is correct, have checked this a million times.

回答1:


If I'm not wrong you are using this wrong. Should be:

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

The token returns others objects, like:

  • email
  • email_verified
  • phone_number
  • name
  • sub

So for you be able to compare the user Id you must use request.auth.uid. This way will compare the cliente client id. If you want to take a look at the docs, is everything abour the request.auth.

Edit

Case you want your own custom token, like: request.auth.token.client_id, you need do that with this code in Python:

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

custom_token = auth.create_custom_token(uid, additional_claims)

Then you can use in your storage rules:

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

See the docs




回答2:


Custom claims are the only way to do this right now. Rules should look like this:

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

where we use two custom fields on the auth token: admin and clientId. The cloud function to sync with the db can look something like this:

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

That runs on any change to the user document, and syncs it to the auth's custom claims.



来源:https://stackoverflow.com/questions/54901291/firebase-storage-rules-with-custom-claims

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!