Search code examples
firebase-storagefirebase-security

Unable to set up firebase storage access rule based on metadata


Facing an issue in setting up access rules. So till now we have been storing user data as <user_id>/. And the basic rule as this has been working fine

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "<UID>/path/to/file.txt"
    match /{userId}/{allPaths=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}   

But now i want a user to be able to store a file under any {userId} as long as he is the owner of the file.

I am doing that by setting the owner metadata attribute when trying to write the file and updating the access rules.

Updated access rules

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "<UID>/path/to/file.txt"
    match /{userId}/{allPaths=**} {
      allow read, write: if request.auth != null
      && (request.auth.uid == userId || resource.metadata.owner == request.auth.uid);
    }
  }
}

I have verified that the metadata is being set correctly by uploading the file to the user’s own path. But when i try to write under some other user’s path, i am getting access denied

See the screenshot of the metadata info of the file i am trying to upload

Image of file with metadata


Solution

  • Finally found the issue.

    I didn't read the documentation carefully. When writing a file, in order to check the metadata of the incoming file, we have to use request.resource. So the write rule had to be request.resouce.metadata.owner

    Updated rule that works

    // Grants a user access to a node matching their user ID
    service firebase.storage {
      match /b/{bucket}/o {
        // Files look like: "<UID>/path/to/file.txt"
        match /{userId}/{allPaths=**} {
          allow read: if request.auth != null
          && (request.auth.uid == userId || resource.metadata.owner == request.auth.uid);
          allow write: if request.auth != null
          && (request.auth.uid == userId || request.resource.metadata.owner == request.auth.uid);
        }
      }
    }