Restrict S3 objects URL only to logged in users on a website - amazon-web-services

My website has some files hosted on AWS S3 buckets, but I need to restrict access to the s3 objects URL to only logged in users of the website. Something similar to how google drive works. which means that anyone trying to access the urls to any of the files on our S3 bucket needs to be logged into the website before he or she would be able to.
Is this possible?
Thanks

If you want to restrict access to the S3 objects, don't make the objects public and don't use the public URLs shown on AWS S3 console.
S3 provides an option to generate pre-signed URLs to download S3 objects. So once your users log in to your website and when they request to download the S3 object, make a request to S3 to generate this pre-signed URL. Clicking on the pre-signed URL will download the object.
With pre-signed URLs, you can configure additional options like expiry time, so that these URLs are more secure.
You can find more info about pre-signed URLs and their implementation here.

If you happen to use AWS Cognito for log in/out functionality, you can assign IAM roles to logged in users.
This way when trying to access the s3 bucket, you can restrict access using IAM roles.
AWS Amplify would be a good fit for this use-case.

Related

AWS: Does my S3 bucket need a policy for files to be readable from my application?

I have a Laravel application that is hosted on AWS. I am using an S3 bucket to store files. I know that I have successfully connected to this bucket because when I upload files, they appear as I would expect inside the bucket's directories.
However, when I try to use the URL attached to the uploaded file to display it, I receive a 403 Forbidden error.
I have an IAM user set up named laravel which has the permission AmazonS3FullAccess applied to it, and I am using that key/secret.
I have the Object URL like so:
https://<BUCKET NAME>.s3.eu-west-1.amazonaws.com/<DIR>/<FILENAME>.webm
But if I try to access that either in my app (fed into an audio player) or just via the link directly, I get a 403. None of the tutorials I've followed to get this working involve Bucket Policies, but when I've googled the problems I'm having, Bucket Policy seems to come up.
Is there a single source of truth on how I am to do this? My AWS knowledge is very limited, but I am trying to get better!
When you request a URL of the form https://bucket.s3.amazonaws.com/dog/snoopy.png, that request is unauthenticated. Your S3 bucket policy does not allow unauthenticated access to the contents of the bucket so that request is denied with 403.
If you want your files to be downloadable by an unauthenticated/anonymous client then create an S3 bucket policy to allow that.
Alternatively, your server can create signed URLs and share those with the client.
Otherwise, your client's requests need to be authenticated, which means having correctly-permissioned credentials and using an AWS SDK.
Typically, back-end applications that you write that need access to data in S3 (or other AWS resources) would be given AWS credentials allowing the necessary access. If your back-end application runs in AWS then you would do that by launching the compute with an IAM role.
Typically, front-end applications would not have AWS credentials. Instead they would either authenticate to a back-end that then does work with AWS resources on their behalf. There are other options, however, such as AWS Amplify apps.

AWS S3 folder permission for users

My scenario is as follows:
Every user on my web application has uuid as primary key.
My web application users can upload images to their own folder(folder name is their uuid,
ex:
clients/0d75db15-07ad-4800-a5de-1fe82a7bf52e/
clients/0faf6315-6ba9-478d-aaa5-3cd2bd3b3b6e/
Every user can only access their own folder and files under the folder.
I know that IAM policies has permissions but not folder level or object level.
Is there any solutions for the scenario?
Thanks for any suggestions and answers!
Given that your application has 1000+ users, you should not be relying on IAM policies or S3 Bucket policies to manage the security.
Instead, all objects should be kept as private and the application should generate Amazon S3 pre-signed URLs, which grant time-limited access to private objects stored in Amazon S3.
It would work like this:
A user logs-in to your application
When user requests access to an image, or if application wants to send them an HTML page that includes images using <img src='xxx'> tags, the application should:
Verify that the user is entitled to access the object
If so, generate a pre-signed URL that grants temporary access to the object
The user's browser then accesses the provided URL
Amazon S3 will verify that the pre-signed URL is valid and then provides access to the object

How to access objects in S3 bucket, without making the object's folder public

I have provided AmazonS3FullAccess policy for both the IAM user and group. Also the buket that I am trying to access says "Objects can be public". I have explicitly made the folder inside the bucket public. Despite all this I am getting access denied error when I tried to access it through its url. Any idea on this?
Objects in Amazon S3 are private by default. This means that objects are not accessible by anonymous users.
You have granted permission for your IAM User to be able to access S3. Therefore, you have access to the objects but you must identify yourself to S3 so that it can verify your identity.
You should be able to access S3 content:
Via the Amazon S3 management console
Using the AWS CLI (eg aws s3 ls s3://bucketname)
Via authenticated requests in a web browser
I suspect that you have been accessing your bucket via an unauthenticated request (eg bucketname.s3.amazonaws.com/foo.txt. Unfortunately, this does not tell Amazon S3 who you are, so it will deny the request.
To access content with this type of URL, you can generate an Amazon S3 pre-signed URLs, which appends some authentication information to the URL to prove your identity. An easy way to generate the URL is with the AWS CLI:
aws s3 presign s3://bucketname/foo.txt
It will return a URL that looks like this:
https://bucketname.s3.amazonaws.com/foo.txt?AWSAccessKeyId=AKIAxxx&Signature=xxx&Expires=1608175109
The URL will be valid for one hour by default, up to 7 days.
There are two ways I will recommend.
go to s3 dashboard, and download the object you need, one by one manually, the bucket can be kept private at the same time.
build a gateway/a small service, to handle authentication for you, set a policy and give the permission to the service container/lambda to visit the private bucket, and restrict only specific users to download the objects.
References
download from aws s3
aws policy, permission and roles

How to set visibility (read) permissions on S3 uploads

Using Amazon's S3 storage, is it possible to set an image to only be viewable to specific users of an application?
I've looked at the policy generator, but I can't seem to find what I'm looking for.
Some of the information on this documentation page sounds relevant. Could I achieve this with signed URLs or IAM users? Ideally, the users of the app do not have to create an AWS account.
By default, all objects in Amazon S3 are private. You can then add permissions so that people can access your objects. This can be done via:
Access Control List (ACL) permissions on individual objects
A Bucket Policy
IAM Users and Groups
Pre-Signed URLs
Given that you wish to grant access to application users, the recommended method is a Pre-Signed URL.
A Pre-Signed URL can be used to grant access to S3 objects as a way of "overriding" access controls. A normally private object can be accessed via a URL by appending an expiry time and signature. This is a great way to serve private content to users without having to define every user within IAM. (It is recommended to only use IAM for staff, not application users.)
A pre-signed URL can be generated from a few lines of code. A quick way to experiment is to use the AWS Command-Line Interface (CLI), which has a aws s3 presign command.
See: AWS CLI aws s3 presign documentation
There are equivalent commands for all AWS SDKs in various programming languages.

Amazon S3 download authentication

I have created a bucket in Amazon S3 and have uploaded 2 files in it and made them public. I have the links through which I can access them from anywhere on the Internet. I now want to put some restriction on who can download the files. Can someone please help me with that. I did try the documentation, but got confused.
I want that at the time of download using the public link it should ask for some credentials or something to authenticate the user at that time. Is this possible?
By default, all objects in Amazon S3 are private. You can then add permissions so that people can access your objects. This can be done via:
Access Control List permissions on individual objects
A Bucket Policy
IAM Users and Groups
A Pre-Signed URL
As long as at least one of these methods is granting access, your users will be able to access the objects from Amazon S3.
1. Access Control List on individual objects
The Make Public option in the Amazon S3 management console will grant Open/Download permissions to all Internet users. This can be used to grant public access to specific objects.
2. Bucket Policy
A Bucket Policy can be used to grant access to a whole bucket or a portion of a bucket. It can also be used to specify limits to access. For example, a policy could make a specific directory within a bucket public to users from a specific range of IP addresses, during particular times of the day, and only when accessing the bucket via SSL.
A bucket policy is a good way to grant public access to many objects (eg a particular directory) without having to specify permissions on each individual object. This is commonly used for static websites served out of an S3 bucket.
3. IAM Users and Groups
This is similar to defining a Bucket Policy, but permissions are assigned to specific Users or Groups of users. Thus, only those users have permission to access the objects. Users must authenticate themselves when accessing the objects, so this is most commonly used when accessing objects via the AWS API, such as using the aws s3 commands from the AWS Command-Line Interface (CLI).
Rather than being prompted to authenticate, users must provide the authentication when making the API call. A simple way of doing this is to store user credentials in a local configuration file, which the CLI will automatically use when calling the S3 API.
4. Pre-Signed URL
A Pre-Signed URL can be used to grant access to S3 objects as a way of "overriding" access controls. A normally private object can be accessed via a URL by appending an expiry time and signature. This is a great way to serve private content without requiring a web server.
Typically, an application constructs a Pre-Signed URL when it wishes to grant access to an object. For example, let's say you have a photo-sharing website and a user has authenticated to your website. You now wish to display their pictures in a web page. The pictures are normally private, but your application can generate Pre-Signed URLs that grant them temporary access to the pictures. The Pre-Signed URL will expire after a particular date/time.
Regarding the pre-signed URL, the signature is in the request headers, hence it should be within HTTPS/TLS encryption. But do check for yourself.