I have Yii2 application where users can upload and share files of different types. Once a file is uploaded, it could be downloaded only by certain other users and there are a whole bunch of checks that go behind this process.
My problem is that the files are stored on the server and if someone has the link directly to the file then they can easily be downloaded without going through any kind of authorization or security checks. How can I prevent this?
P.S. It could be any kind of solution, not one related to Yii2.
The following approach comes to my mind.
Store the files at a location in file system that is not made publicly accessible by a web server.
Make them available by reading them from file system and sending them to browser when the user retrieves the URL that also does the security checks. A redirect to another URL that does not do security checks has to be avoided.
If you give more details about a more specific problem or question people can give you more specific information.
Related
I am trying to develop a WebExtension that accesses a user-defined API whose URL I do not know in advance. (More specifically, it manages their Ghost publications, whose APIs would be hosted on the same domains as the publications themselves). Hence, I need to let users enter their API URL and access that throughout the addon.
The simplest way to do this would be to request the <all_urls> host permission (basically like *://**). But instead of such sweeping permissions, I was wondering if there's a more finegrained way of requesting permission just for the specific URL I need?
I know that the optional_permissions setting lets an addon request additional permissions at runtime if those permissions are specified in advance in the manifest. From this w3cub page:
Type
Mandatory
Example
Array
No
"optional_permissions": ["*://developer.mozilla.org/*", "webRequest"]
Use the optional_permissions key to list permissions that you want to ask for at runtime, after your extension has been installed.
However, this seems to require a hard-coded permission (*://developer.mozilla.org/*) that's requested at runtime. What I need is a user-defined permission that can be requested in the same manner. Is there any way I can go about implementing this?
From the list of use-cases for optional permissions on the Mozilla docs:
The extension may need host permissions, but not know at install time which host permissions it needs. For example, the list of hosts may be a user setting. In this scenario, asking for a more specific range of hosts at runtime, can be an alternative to asking for "<all_urls>" at install time.
The way to do it is to include <all_urls> in the optional_permissions setting of your manifest.json like this:
"optional_permissions": [
"<all_urls>",
"webRequest",
"geoLocation"
],
In this example, we're also requesting the webRequest and geoLocation permissions; this is to demonstrate the two different kinds of permission you can request.
Then, in your code, instead of requesting <all_urls>, just request the URLs that you actually want to access:
browser.permissions.request({
permissions: ["webRequest", "geoLocation"],
origins: ["https://example.com/*"]
})
As you can see, the request is neatly separated into an option for more API permissions and another for the different websites (origins) you want to access.
A more complete example can be found on the docs for permissions.request docs. (You can also find a working sample webextension here, but it doesn't include host permissions, only API ones).
I’m looking to hopefully write a function that protects WordPress media files (or more specifically pdf files).
I would like this function to run when a user attempts to access a specific file.
What I would like to happen is:
User attempts to access url of specified file/files
Function/Action runs the following checks
Check to see if user is logged in
Checks to see if user is either subscribed to a specific WooCommerce product, or has purchased a specific product.
If user meets the requirements, access is granted to files
If user does not meet the requirements they are directed to 404.
I realise WooCommerce already has a system for connecting files to products however having a function like this would be easier, as I plan to tie it in to ACF. I have a variation of this code working on the front-end however this does not protect the media files. Any help would be greatly appreciated.
<?php if (is_user_logged_in()) {
if (wc_memberships_is_user_active_member($user_id, 'gold-membership') || ( wc_customer_bought_product( '', get_current_user_id(), 999 ) ) ) {
} } ?>
Better upload pdf to outside uploads folder of the Wordpress.
In the wp-content/uploads the files will stay public access.
Only read and offer files via script, this mode you can control the access of files.
I am creating a REST API for my next project. I am not sure what the best way to handle read / write permissions on resources is. Some resources will be readable by anyone, others will only be readable by "logged in" users, others will only be readable by specific users or admins. This also goes for write access.
How are these permissions stored and validated in REST APIs. Are there simply database tables that store the permissions for each resource or the permissions each user has to each resource? This approach seems like it could become bloated if there were many resources to keep track of not to mention every database query would require a JOIN to the table that contains permissions.
Thanks for your input in advance!
How your server side stores authentication and authorization data is entirely up to the server. It may use a database, it may use files, or none of the above.
From the perspective of RESTful HTTP, the point is that client might try to access some resource, the server may answer with 401 (Unathorized/Authentication required) or 403 (Fordbidden) HTTP error codes to enforce login/permission requirements.
Also remember, that not all services map directly to one or more relational database queries. In other words, plan to implement the authentication/authorization logic independently of the "data" if you can, and if you need fine-grained access restrictions, try to do it in code instead of joining stuff in the database, if it's possible.
My app uses the Drive rest API and the Drive Realtime API in combination. We set the file's permissions so that the public has view access, and then emailed a link to it to a few thousand customers.
The file's permissions are set so that the public has view access, but:
When a user tries to open the realtime document, we get Drive Realtime API Error: not_found: File not found.
When a user tries to copy the non-realtime file, we get The authenticated user has not granted the app 689742286244 write access to the file 0B-NHh5QARZiUUFctN0Zjc3RKdWs (of course we are not asking to write
You can see the effects for yourself at https://peardeck.com/editor/0B-NHh5QARZiUUFctN0Zjc3RKdWs , and our embarrassing attempts to cover for the errors.
Interesting notes:
Sharing the file directly with a particular google account seems to lift the curse, and then that google account can find the file like normal. No extra permissions, just an explicit reference to a google account.
Setting the file so that the public has full write access seems to have no effect
Other files with the exact same settings in the exact same Drive folder can be opened successfully (but presumably have not been opened by so many people in the past). This makes me think there is some broken state within Google.
How can I avoid this? What's going on?(!?!?) Thanks for any help!
The realtime API does not support anonymous access. All users must have a Google account and be explicitly authorized to view or write to the file.
I have two different CakePHP based applications on same server. They are placed in separated directories, and each of them use it's own database. Also, they both have implemented authentication. So, (in my opinion) they are fully independent.
Problem I have is that I cannot be logged-in in same time in both applications (in same browser).
Can you help me what I'm doing wrong in this case, and how can I be authenticated in both of them sametime?
Try to change Session.save variable in app/config/core.php. Default is 'php', so change it to 'cake'. This will make Cakephp store the Session variables in the app/tmp/sessions directory. Remember to give write permissions to this folder. Also make shure that both apps have diffrent Security.salt key in the same config file.