parse-server: beforeGetFile trigger

Is your feature request related to a problem? Please describe. With the addition of file triggers, the only one that is missing is beforeGetFile. Let’s say that I want to restrict fetching a file to only the user who initially created it. Currently there is no way to do that since anyone with the file url can access it.

Describe the solution you’d like Add a beforeGetFile file trigger so that an additional layer of security can be added when fetching files

Describe alternatives you’ve considered None

Additional context Currently anyone who has the file name/url can retrieve a file. Adding a beforeGetFile trigger will allow for additional file security. My plan is to use the beforeSaveFile and afterSaveFile triggers to keep track of files and who created them. I can then use the beforeGetFile to restrict access to only the files they have created. The challenge is there is no session token passed in when retrieving files. I have no problem tackling this feature request, but I would like to get feedback on the best way to approach this?

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 2
  • Comments: 32 (28 by maintainers)

Most upvoted comments

We use the local system to store files, and we need beforeFind for file security. If possible, please look into this matter further. Thank you.

I have edited my previous comment a couple of times, so you may want to reread it.

Well as I said that if we add the trigger, req.user will always be undefined if the file is accessed via URL.

If a session token is sent in the request header, then the req.user should be set. If the session is missing (e. reference in an <img> HTML tag), then one could implement their custom token strategy via the triggers I proposed above.

Parse Server could of course offer a token functionality OOTB, but I think the most versatile step may be to open Parse Server up for URL customization via file triggers. These triggers are likely required internally to implement any OOTB solution, so we may as well break this down into smaller PRs and expose them first.

I think @brunobg has a point. Maybe we can start off with adding simple triggers, so anyone can implement their own concept of file access permission. Then we can think about a built-in ACL for files in a separate step.

There could be 2 triggers, 1 before a file URL that is generated by the storage adapter is returned and 1 before a file URL is parsed in the process of a file request. So it’s possible to customize the URL that is sent to the client and customize the URL interpretation when a file request is triggered with the customized URL.

You could for example replace the filename with a token that includes the user ID, the filename and an expiration date and you need the master key to decrypt that information. Then when a file is requested, the server can try to decrypt and give permission if the requesting user is correct and the token has not expired. Or one can create a simple lookup function in a custom class for the filename and the associated user relation. Anyone can build their own algorithm.

So every time a file is requested, a lookup happens in that class and the ACL is applied. Files would be compared by filename as their UID.

I think the problem with this approach is ParseFile urls are static (unless you are using presigned URLs PR on the S3 adapter, which is great by the way), so if you had ACL permission to the File class, you can share the URL with anyone publicly and there is no way to verify ACL of the file being accessed by its public link, unless we add some sort of internal generated ID and expiry time for when the File is requested.

My thinking is that when someone accesses the public Parse File link, that is when the trigger would fire and try to find the associated File Class and permissions.

Btw, this File class is something we have also discussed for a file cleanup feature, so it would be a step into that direction.

Agree!

I think Parse Server could restrict certain files to certain users while allowing anonymous downloads for other files.

  • If you have an image that will be embedded on a website, you simply don’t have to restrict it.
  • If you a have a sensitive document then you can restrict it (and provide header auth info in the request).

Setting permission per file may be something that should really be done on the resource site. For example, if you store a file on AWS S3, you could use AWS IAM and link that to the Parse Server User class via an identity broker, so that you can reference S3 file permissions using Parse Server User IDs. That’s the safest way, because it’s on the lowest resource level, regardless from where the access request comes.

If we want to “fake” these storage permissions in Parse Server, we’d probably need a central list of files. Because a Parse File can be referenced in many places, but binding a permission to only one of many references doesn’t make much sense. We could create a new internal class File and if a file should be restricted, add an entry there with the file pointer and a fileACL field. So every time a file is requested, a lookup happens in that class and the ACL is applied. Files would be compared by filename as their UID.

Btw, this File class is something we have also discussed for a file cleanup feature, so it would be a step into that direction.

It would be good to have an option for something like req.file.download = true so you can force files to download.

I’m happy to work on this, but I believe the only concern is it’s impossible to determine req.user when files are accessed via a get request to a URL (as browsers don’t pass in req headers for <img src="parsefilurl" />). Adding req.user would require some sort of FileObject class as well as tokens in the URL param to determine ID of user requesting the get.

Do you have any ideas @mtrezza?

I’m all for this request. With parsed-based file URLs the way they are now, it is a security issue. Once someone has the URL, they have it forever and can access it without any kind of authentication or authorization.

I am all for beforeFindFile and afterFindFile triggers. I think this is a very valid feature request, in fact I just posted a SO question before finding this.

Of course direct access for S3 means that the 404’s would have to be detected from the S3 server access logs, but that is something Parse Server doesn’t have to account for.