-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
beforeGetFile trigger #6572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This sounds like an interesting idea but it is hard to implement systematically since for example with S3 adapter the URL points directly towards S3 after upload and the file download does not go through the parse server, which is a good thing IMHO for performance reasons. Could probably work with GridFSAdapter. |
If you're using direct access to your S3 adapter you are correct. The only way to implement this would be if you do not use direct access |
I am all for 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. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
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. |
@dsyrstad If it helps, it is possible to create temporary URLs, depending on how you store your files. For example, for AWS S3 there is an open feature request to support pre-signed URLs. |
The expiration would be managed by the storage service, but the Parse Server storage adapter would request the temporary URL from the service. I think this is already implemented in the Azure storage adapter, but if you want that for S3, you could continue the PR that already exists. |
It would be good to have an option for something like I'm happy to work on this, but I believe the only concern is it's impossible to determine Do you have any ideas @mtrezza? |
I think Parse Server could restrict certain files to certain users while allowing anonymous downloads for other files.
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 Btw, this |
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.
Agree! |
Related #7001 |
There are 2 ways to share a file:
In case of (a) you can easily do the File class lookup on request as Parse Server sits between client and storage resource. In case of (b) you can only restrict that on the resource side, that's what I mentioned above with the identity broker. Currently it means you are giving up Parse Server control over the file access. |
Forgive me I’m sure we’ve had this discussion before around the best approach to this issue.
Yes, you can easily identify the file through the request, but how do you identify the |
If a file has an ACL set, then you look for auth headers. If there are none, you deny the request. In practice we would try to re-use existing auth logic of other routes and add it to the file route of Parse Server. |
Yes, but if my understanding a file is embedded or opened via hyperlink, headers aren’t set, meaning that the file would be denied if embedded in a html file, imageview, etc, rendering it practically useless unless fetched via a library such as |
That's correct. I would say that's the default behavior of a browser. As a website provider you don't control the headers that a browser is sending to your server. It seems you have a specific scenario in your head; if you want to share that scenario we can look at how and whether this feature fits into your scenario. |
Yes, so my thoughts are that if you’re currently using Parse Files to serve a users Photos or Passport (for example), you most likely have that embedded via a src link, or an action that opens the Parse File URL in a new window. If you use this new feature which requires headers, this functionality would break and you would have to embed the image via:
I’m suggesting that we use URL parameters to pass a token so that the File URLs can still be embedded without needing a specific method and code refactoring across every SDK, but I guess if this is a security feature recommended for specific secure files, developers will probably be happy to refactor their client code. |
I assume the token is to authenticate the request as a specific user. In your scenario, what should be the characteristics of that token, e.g. how long should it be valid, etc? |
Well initially I was thinking assigning each File class object a TOTP secret that can be used to generate TOTPs that auto-expire in a dedicated period (e.g 300 seconds). That way all the auth can happen at the FileObject level by Parse Server's internal CLPs / ACLs, then if valid, generate the TOTP code, assign it to the URL param, then delete the secret from the payload. It would be a way to handle "presigned URLs" without having to store tokens. Alternatively, we could generate tokens and expiry times aligned to a specific file (again handling the ACLs as Parse normally does with pointers), and store them as a relation between the FileObject and a |
What is the relation between expiring token and user, where would that be stored? |
Well I'd assume it would just be a relation between a FileObject and FileToken, and I think that all would need to be stored on FileToken is objectId, expiry_date, and maybe user. So, when a FileObject is saved, it has ACLs. When a file is retrieved if the permissions are valid, generate a random token, append it to the file URL, and create a |
OK, so these are two separate features:
Maybe we should look at them separately and look at (a) first. (b) may be something Parse Server doesn't need to implement, as many storage providers already have such a feature and it may be something that can be incorporated into the storage adapter's Can you outline the process for (a) you have in mind in a 1. / 2. / 3 step-by-step format, from file upload to file download, so we understand when should happen what, where is info stored, where are potential perf implications. |
What about allowing a simple |
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. |
Well as I said that if we add the trigger, I just think from a completeness perspective, it would be better to introduce the trigger with |
I have edited my previous comment a couple of times, so you may want to reread it.
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 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. |
Sounds like a good idea to me. What would you propose the secondary trigger to be named? |
If the |
What would you think about beforeCompose: runs on compose file and then add: |
Sounds good, is there another word for "compose" that could be used more universally (also for classes) in the future? Maybe a beforeCreate? |
We use the local system to store files, and we need |
Just a note that it could be pretty easy to add a service worker to the SDK for the browser to pass in the Session Token header automatically for GET requests to the Parse.ServerUrl |
🎉 This change has been released in version 8.1.0-alpha.2 |
🎉 This change has been released in version 8.1.0 |
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
andafterSaveFile
triggers to keep track of files and who created them. I can then use thebeforeGetFile
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?The text was updated successfully, but these errors were encountered: