How to get access to private s3 bucket using cognito - amazon-web-services

I have a cognito user pool which is connected to google as identity providers (so that I can log in with a gmail account). I also have a private bucket s3 with files (). How can I use my lambda function, using the token returned by Cognito (AcessToken, IdToken) to get access to my s3 bucket which is not public?
I just want to use my cognito to access my private files on s3.
Something like the Cognito Authorizer for lambda functions just for s3 bucket.

You can use Signed URLs to achieve this.
Basically, after your user successfully authenticated by Cognito, your Lambda function will generate s3 pre-signed url for object requested and reply it back.
Example from AWS Documentation
Also take a look at this AWS forum thread

The only way that i know to do this is give the role access to the cognito user
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_s3_cognito-bucket.html

Related

Turning off public access to AWS S3 bucket

I understand that you can grant read/write to internal AWS account resources like lambda when you turn off public access. However what if I need to be able to read an S3 object from an external host, via the S3 URL? Sure I know I could add a public API endpoint to serve up the S3 asset. However if I use something like <img src=""/> that doesn't help me. If I try to perform a GET on the S3 url at this point, I get a 403. I'm wondering in this case that I have to leave 'public access' on?
There are two ways to access objects in private Amazon S3 buckets.
Use S3 API calls
You can use API calls using the AWS CLI or an AWS SDK. These API calls require AWS credentials that have GetObject permission to access the bucket. They do not require the bucket to be public.
Use a pre-signed URL
Alternatively, you can generate an Amazon S3 pre-signed URL, which provides time-limited access to private objects in Amazon S3. The URL can be used in <img src=...> tags.
The pre-signed URL can be generated in a few lines of code without the need to call AWS. It is basically a hashed signature that uses some AWS credentials to authorise access to the private object. This option appears most suitable for your use-case.

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

Authenticate s3 request based on both file and request

Let's say I want to store some files for each user which is using my website on s3. Later I want authenticate each request to s3 to make sure that user has access to the files she is requesting. I guess this can't be done using presigned URLs or signed cookies(using cloud front). So which Amazon service should I use for that? What is the simplest way to achieve this?
Lets saying I'm authenticating users using jwt and its possible to recognize wheather a user has access to a file or not by the filename and content of the jwt.
I'm sorry that I don't have enough reputation to comment so I'll post an answer here.
One solution is:
AWS Cognito (Federated Identities)
S3 (one bucket)
S3 bucket policies allow you to restrict access to "user folders" equivalent here to "identity" by the prefix like yourbucket/<cognito_identity_id>/* Each user on your webpage will have its own federated identity.
When you create and configure the identity pool in AWS define a custom authentication provider and authenticate users "by the developer" in your backend.
Also, associate the authenticated identities to one IAM Role with access to the S3 bucket where you will keep the data. The bucket policy will take care of only allowing each user to their files and not to others. (See referenced links for policy example and more)
Amazon S3: Allows Amazon Cognito Users to Access Objects in Their Bucket
Access to User level folders using Amazon S3 and Cognito
Developer Authenticated Identities (Identity Pools)

How to make private bucket on AWS s3?

I'm trying to make a private bucket on AWS s3 and read and write to it from an Android App.
I found many of resources and questions but nothing of it gave me a complete answer.
I made a private one but don't know what should I write in Bucket Privacy, and what I need to access it from an Android app.
How can I do it?
More details:
My app is an e-commerce app has users, they upload photos to the app and view it from a website and from the app too.
All data on my server except photos, I want to upload the photos to a private bucket on s3 and view those by URLs saved on my server. Can I do it?
Restrict access to IAM role for S3 bucket. Use this role in Android App.
The normal architecture for this is:
Keep the Amazon S3 bucket private (no Bucket Policy)
Users of the Android app provide their login information to the app, which authenticates against your back-end service
Once authenticated, your back-end service can generate temporary credentials using AWS Security Token Service (STS) — permissions are assigned to these credentials that grant access to Amazon S3 (eg only for a certain path within a particular bucket)
The mobile app can then use these temporary credentials to directly communicate with Amazon S3 to upload/download objects
You could use Amazon Cognito for authentication and provisioning of credentials, or you could code your own authentication process (eg checking against your own database).
References:
Using Amazon Cognito for Mobile Apps - AWS Identity and Access Management
AWS IAM Now Supports Amazon, Facebook, and Google Identity Federation | AWS News Blog
About SAML 2.0-based Federation - AWS Identity and Access Management
If you only wish to view photos, then a simpler method would be for the back-end to generate Amazon S3 pre-signed URLs, which permit time-limited access to private objects in Amazon S3.
See: Amazon S3 pre-signed URLs
You can do this both by:
creating a bucket policy for specific IAM user
creating an ACL policy for an account and then delegating permissions to a specific user

Allow access to custom prefix on S3 with Cognito

I need to allow users to access files on S3 with a specific prefix -- ie username1 -- that I can't change, so I can't just use the ${cognito-identity.amazonaws.com:sub} as the prefix. My S3 bucket is already populated with content under specific prefixes - so a user logs into my app, and is then allowed to access one of those specific prefixes
Currently set up on AWS to allows users to authenticate in a Cognito role using Firebase and developer authenticated identities. Each user account (email/password) has an associated S3 prefix that they must be able to access. Some users will share this prefix (two users accessing S3-bucket/username1 for example). A user should not be able to list or access any other prefix except their associated prefix.
I'm not quite sure what the best way to go about accomplishing this -- just with Cognito roles or using a database and lambda function + api endpoint, bucket/user policies or ACLs. Is there a simple way that I'm missing?
Pretty new to AWS, any help will be greatly appreciated!
tl;dr: How to only allow a user to access files on S3 with a specific prefix, that is NOT the ${cognito-identity.amazonaws.com:sub} variable?
As mentioned in comments, Amazon Cognito does not directly support your use case today. You can implement something like the following to achieve your goals:
Use Cognito to authenticate your users as normal. The Cognito identities would have permissions to invoke an API Gateway endpoint.
Your API (running in a Lambda) uses the Cognito identity id (provided in the context) to lookup the mapping of Cognito identity to your custom S3 prefix.
Your API uses STS to generate temporary credentials to access that prefix, returning them to the client.
The client uses those credentials to make a request directly to S3.