How to serve static files securely using google app engine with django? - django

Currently my website runs on google app engine with Django and my static files are served using google cloud storage. I had explored the documentations and I could not find a easy way to serve my static files securely.
Let say i am logged in as a user into Django site. I only want the logged in user to see the picture and other user can't see the picture.
Currently the picture is serve using a link to the google cloud storage and the access are made public.
However, that means that anyone with that link can view that picture. How do i make sure that only the logged in person with the link can view the image instead of everyone with the link can view it, is there any way to do it with google app engine standard, google cloud storage and Django?
I also know that google cloud storage can have some form of access control but how do i link that part with Django users?

Maybe you can set your bucket acl to private and implement Signed URL feature for your purpose.
https://cloud.google.com/storage/docs/access-control/signed-urls
For Python take a look at documentation about signed URLs: https://googleapis.github.io/google-cloud-python/latest/storage/blobs.html#google.cloud.storage.blob.Blob.generate_signed_url

Related

How to implement NFT-gated website for existing website that is not a dApp

I have one website (WebsiteA) that needs user login to access the system. Inside user has NFT collections that are saved in the blockchain.
On the other hand, I have an existing website (WebsiteB) that I want to restrict user access on some of its features. It has it's own user login separate from the first website I mentioned. I want to call some service from my first website (WebsiteA) that will check if the user currentluy logged in in my existing website (websiteB) has the necessary NFTs.
As the existing website may have it's own authentication already setup, while WebsiteA can be used not only by WebsiteB but also by other existing websites, how do I setup the authorization between existing websites and my new website?

Google storage bucket (google api link) integration with Cloud CDN

Respected seniors!
I have hosted a website on GCE and storing all static content on GCS bucket. The content is then accessed using google API link e.g https://storage.googleapis.com/[BUCKET_NAME]/[OBJECT_NAME]...
Now the API link is embedded on webpage on my website as https://www.example.com/post/[random post number](this is an html link which I need to serve an updated copy every time so I set up a cookie to avoid caching in CDN)
I have enabled Cloud CDN on my load balancer backend GCE. My understanding was that the link embedded in webpage for static content will automatically be cached in CDN because the bucket access is made public.
Upon verifying using cURL I came to know that whenever I access the object using API link (https://storage.googleapis.com/[BUCKET_NAME]/[OBJECT_NAME]), the content is cached in CDN and whenever I use my site link (https://www.example.com/post/[random post number]), the content is not cached.
Kindly suggest any method to cache the content on bucket in clod CDN whose link is embedded in dynamic content url which has to be fetched fresh every time.
Thanks in advance
Based on your description, this look like working as intended. The reason why the content is not being cached is due to cookies header being present.
This article explain when content is non-cacheable: https://cloud.google.com/cdn/docs/caching#non-cacheable_content
This is also confirmed when you mentioned:"(https://storage.googleapis.com/[BUCKET_NAME]/[OBJECT_NAME]), the content is cached in CDN." The bucket doesn't have any cookies and this is why it's cached.

Secure image Urls

I am making a app that allows users to upload images to their profile page. I was using firebase Storage to store the images using a folder for each user. The problem I have is the Url for the images are accessible without evening signing into my app. Can I limit access to users that have signed in to my app? Im using a custom sign in token. Or do I need to switch to another storage provider.
It sounds like you're using Firebase Storage's download URLs. These are (by definition) URLs that give anyone who has them read-only access to the file. Download URLs are only generated when you call getDownloadUrl() (or the equivalent method on the platform you use). So if you don't want this behavior, don't call getDownloadUrl().
If you don't have a download URL, the files in Storage are only available by using the Firebase SDK. At that point all access to the files is secured through the security rules that you've defined for your project. For more on this, see the Firebase documentation on securing access to files.

How should a web application ensure security when serving confidential media files?

Question: Say a user uploads highly confidential information. This is placed in a third party storage server. This third party bucket uses different authentication systems to the web application. What is the best practice for ensuring only the user or an admin staff member can access the file url?
More Context: A Django web application is running on Google App Engine Flexible. Google Storage is used to serve static and media files through Django. The highly confidential information is passports, legal contracts etc.
Static files are served in a fairly insecure way. The /static/ bucket is public, and files are served through django's static files system. This works because
there is no confidential or user information in any of our static
files, only stock images, css and javascript, and
the files are uglified and minifed before production.
For media files however, we need user specific permissions, if user A uploads an image, then user A can view it, staff can view it, but user B & unauthenticated users cannot under any circumstances view it. This includes if they have the url.
My preferred system would be, that GCP storage could use the same django authentication server, and so when a browser requested ...google.storage..../media/user_1/verification/passport.png, we could check what permissions this user had, compare it against the uploaded user ID, and decide whether to show a 403 or the actual file.
What is the industry standard / best practice solution for this issue?
Do I make both buckets only accessible to the application, using a service account, and ensure internally that the links are only shared if the correct user is viewing the page? (anyone for static, and {user or staff} for media?)
My questions, specifically (regarding web application security):
Is it safe to serve static files from a publicly readable bucket?
Is it okay to assume that if my application requests a file url, that this is from an authenticated user?
Specifically with regards to Django & GCP Storage, if 2 is false (I believe it is) how do I ensure that files served from buckets are
only visible to users with the correct permissions?
Yes, it is. Public readable buckets are made for that. Things like, CSS, the logo of you company or some files that have no sensible data are safe to share.
Of course, do not use the same Public bucket to store private/public stuff. Public with Public, Private with Private.
Here is the problem. When you say "authenticated user", to whom you want that user to be authenticated to?
For example, if you authenticate your user using any Django methods, then the user will be authenticated to Django, but for Cloud Storage it will be an stranger. Also, even a user authorized on GCP may not be authorized to a bucket on Cloud Storage.
The important thing here is that the one that communicates back and forth with Cloud Storage is not the User, its Django. It could achieve this by using the python SDK of Cloud Storage, which takes the credentials of the service account that is being used on the instance to authenticate any request to Cloud Storage. So, the service account that is running the VM (because you are in Flexible) is the one that should be authorized to Cloud Storage.
You must first authorize the user on Django and then check if the User is able to access this file by other means(Like storing the name of the file he uploaded in a user_uploaded_files table).
Regarding your first question at the top of the post, Cloud Storage lets you create signed urls. This urls allow anyone on the internet to upload/download files from Cloud Storage by just holding the url. So you only need to authorize the user on Django to obtain the signed url and that's it. He does not need to be "authorized" on Cloud Storage(because the url already does it)
Taken from the docs linked before:
When should you use a signed URL?
In some scenarios, you might not
want to require your users to have a Google account in order to access
Cloud Storage, but you still want to control access using your
application-specific logic. The typical way to address this use case
is to provide a signed URL to a user, which gives the user read,
write, or delete access to that resource for a limited time. Anyone
who knows the URL can access the resource until the URL expires. You
specify the expiration time in the query string to be signed.
Following on from Nahuel Varela's answer:
My system now consists of 4 buckets:
static
media
static-staging
media-staging
Both the static buckets are public, and the media buckets are only accessible to the app engine service account created within the project.
(The settings are different for dev / test)
I'm using the django-storages[google]with #elnygrens modification. I modified this to remove the url method for Media (so that we create signed URLS) but keep it in for static (so that we access the public URL of the static files).
The authentication of each file access is done in Django, and if the user passes the test (is_staff or id matches file id), then they're given access to the file for a given amount of time (currently 1 hour), this access refreshes when the page loads etc.
Follow up question: What is the best practice for this time limit, I've heard people use anywhere from 15mins to 24 hours?

Google account authorization for users accessing google docs

I am pulling list of docs in coldfusion via google docs API. I want users to click on the link and get signed in automatically in google docs, with my username and password. Google should not ask user name and password from them.
I tried out this example http://cfgoogle.riaforge.org/
Till now I am able to pull up list of documents I have on my google docs account.
But I want anyone to click those link and get automatically signed in as me. And able to access my documents. Is it possible?
I would guess that accessing the documents as you is not possible via the end-user's browser. Google will set a cookie on your computer identifying your session. This allows you access to documents, mail, etc. whatever is linked in your account. For them to be able to access the documents using your account, they would have to be logged in as you. You can't do that directly from your application, because you can only write cookies for your domain (oversimplification, but basically....)
There may, however, be a workaround.
One option would be to use the API to automatically share the document with the user. That is, they provide their Google ID (not password) and you share with their account. This is probably what I would try.
Alternately, you could proxy requests for documents, although this opens up a whole 'nother can of worms.