I have a bunch of images on my S3 which is linked with Cloudfront.
Now I have a web server and I only want users to view the image through my website so I can't just give out links to the image. How do I set that?
It appears that your requirement is:
Content stored in Amazon S3
Content served via Amazon CloudFront
Content should be private, but have a way to let specific people view it
This can be accomplished by using Pre-Signed URLs. These are special URLs that only work for a limited period of time.
When your application determines that the user is entitled to view an image, it can generate a Pre-Signed URL that grants access for a limited period of time. Simply use this URL in an <IMG> tag as you would normally.
See:
Amazon S3 pre-signed URLs
Amazon CloudFront pre-signed URLs
Since your content in Amazon S3 will be private (so users cannot bypass CloudFront and access it directly), you will also need to grant CloudFront permission to access the content from S3. See: Using an Origin Access Identity to Restrict Access to Your Amazon S3 Content
Another option, instead of creating a pre-signed URL each time, is to use Signed Cookies. However, this doesn't give fine-grained control for access to individual objects -- it's more for granting access to multiple objects, such as a subscription area.
Related
I have a bunch of 3D models on my web app and they are accessible to public to see but I don't want anyone to download them. I use Amazon S3. Is there any way to achieve this?
In the default web app - as already commented - if the client can "see" the resource, it is already on the client's side.
There are two aspects of the question. You want to prevent accessing the models from the public (unauthenticated) client or even the authenticated.
To prevent unauthorised access to S3 resources used for web apps, the common option is using the pre-signed S3 url. The application generates temporary resource link only for authorized users.
If you want to prevent access to resources even authorized users, to you can render the view on the server side e.g. see AWS AppStream
I have a single-page app that is developed in one of the modern JS frameworks.
This single-page app only has a single entry point (index.html).
It handles routing and other page logic through JS, which means that when a user goes directly to, or refreshes the page on, a non-root URL we want them to pull down the index.html file instead of a file stored at the URL path location (like in a statically hosted website).
If a resource behind the URL is not found, S3 returns 403. Therefore, in CloudFront, we have configured the following rule:
Now, I am working on the Authorization layer in the backend that legitimately is returning 403 if the subject doesn't have enough rights to access the API.
And, instead of returning 403, CF, for obvious reasons, is returning 200 with the index page.
Is there a way to fine-tune this behavior? Thoughts?
I was able to solve this by using the following approach:
turn on Static Web Hosting on S3
replace the S3 bucket name in CloudFront origin with the S3 Static Website URL.
remove Error Pages from CloudFront.
The error pages will be handled by the respective origins instead of CloudFront.
I have a MEAN stack app built where the user can upload images. Currently, I'm storing the URLs of the images in mongodb, and the images themselves in the filesystem in a specified folder. I've read that it's better to store these images somewhere like AWS or firebase for scalability, so I decided to go with AWS.
I created a bucket and can upload images fine via multer.
How can I allow users to only retrieve their images when they are logged into my app? The authentication in the frontend and backend is already finished, but I can't figure out how to use this with accessing the s3 bucket and only getting the user specific images.
I could make the bucket public and easily build the URLs, but that means everyone (regardless if they are logged into my app or not) can access them, which is not what I want.
If you can authenticate your users as Amazon Cognito users then during a login they will assume a role.
If that role has a policy attached for S3 you can use the ${cognito-identity.amazonaws.com:sub} variable. By structuring your S3 bucket to use key paths containing this variable in it you can develop a policy that will only grant access to keys with the prefix of that user id.
Take a look here for an example S3 policy.
I am using NodeJS to upload a file into my S3 bucket. As a response I receive a link to the file.
For example I receive https://my-bucket-name.s3.ap-south-1.amazonaws.com/testUpload_s.txt
The bucket does not allow public access as of now. How am I supposed to securely access the file from the bucket? I would like to know whether the the following method be safe?
Allow public access for bucket
Each file will be given a random unique name during upload
This file name or the response URL is stored in the database
When the file has to be fetched I use the link received from the
upload response to access the file from the bucket
Is this approach safe? If not is there any other method to do the same?
There are a number of options for giving clients access to an object in S3, including:
make the object public
require the client to authenticate with AWS credentials
give the client a time-limited, pre-signed URL
They each serve a different use case. Use #1 if it's safe for anyone to access the file (for example the file is an image being shown on a public web site). Use #2 if the client has AWS credentials. Use #3 if you don't want to make the file public but the client does not have AWS credentials. Note with #3 that the pre-signed URL is time-limited.
You don't need to store URL. You can query objects in S3 bucket using file name.
For access from outside Use signed url.
https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/s3-example-presigned-urls.html
We are storing files uploaded by users of our app to Amazon S3.
In order to keep these files private & secure, we are:
having the client generate a UUID for the filename (so that the URL of the file is difficult to guess). See: What is the probability of guessing (matching) a Guid?
going to protect the data by using client-side encryption.
Do these two measures provide sufficient security, or should we also use Amazon Cognito to ensure that the user getting the object is one of the users who has access to it?
Using obscure filenames is not a good security method.
If you wish to allow users to upload/download data to/from Amazon S3 in a secure manner, you should use Pre-Signed URLs.
The process is:
Users authenticate to your web/mobile application
Users interact with your application and indicate they wish to upload/download a file
Your application generates a pre-signed URL that includes an authorization to access Amazon S3, with restrictions such as bucket, path and file size
Users upload/download the file using the pre-signed URL
This way, your application controls the security and there is no potential for accidental workaround, overwriting, access, etc.
See: Uploading Objects Using Pre-Signed URLs