1

I need to secure my s3 bucket objects. In my web application I'm using aws-sdk to upload media to s3 bucket and get an http link back to access that object. This http link is public by default and I want to make it secure so that only authorized users can access the media. aws s3 allows to make the object private but it wont let anyone with the link access the object.

This link will be accessed from a mobile app where I dont want to use aws-sdk, Instead I want to execute some logic on aws side whenever someone tries to access the http link for the object.

What I would like to happen is, before the user gets access to s3 object, Some authorizer code would execute (like a jwt token authorizer) and depending on it user would be granted/denied access.

I'm currently looking into Amazon API Gateways, I believe they can be accessed as an http link and AWS Lambda could be used to secure them(where i would execute my jwt authorizer). Then these apis would have access to s3 internally.

If someone could point me in the right direction, If this is at all possible. If I could use the same jwt token issued from my web-application to send along the request to Amazon API Gateway, that would be great.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
Akash Sarode
  • 387
  • 2
  • 13

3 Answers3

3

I would make the bucket private, and place a CloudFront distribution in front of it. Using an Origin access identity to allow only CloudFront to directly access the S3 bucket.

Then to provide security I would use either CloudFront signed cookies, or Lambda@Edge with a custom JWT token validation.

Mark B
  • 183,023
  • 24
  • 297
  • 295
1

The easiest solution to expose private objects in an S3 bucket is to create a pre-signed URL. Pre-signed URLs use the permissions from the service (which pre-signs the URL) to determine access and have only a limited duration in which they can be used. They can also be used to upload an object directly to S3 instead of having to proxy the upload through a lambda function.

For a download functionality and a smooth user experience, you can - for example - have a lambda function that generates a pre-signed URL and returns it as an HTTP 302 response, which should instruct the browser to automatically download the file from the new URL.

(Edit)

Following on what I've stated in the comments on this answer, if you're proxying the upload/download of the objects through services such as API Gateway or Lambda, you will be severely limited in the size of files that you are able to upload to S3. The payload size limit on an API Gateway is 10 MB and for requests to lambda your payload is capped at 6MB for synchronous invocations. If you want to upload something larger than 10 MB, you will need to use direct upload to S3 for which pre-signed URLs are the safest solution.

stijndepestel
  • 3,076
  • 2
  • 18
  • 22
  • It requires you to know the S3 object key, all I have is an S3 Object URL (https://s3.amazonaws.com/...). The mobile app is only going to consume the files in the bucket with the Object URL, uploading and deleting those files is done with a web application dashboard, there I'm using aws sdk. I am trying to simulate the behaviour of a typical web app using token authentication. – Akash Sarode Aug 18 '21 at 08:43
  • You can easily get the object key from the S3 URL as it is an integral part of the URL. You can always proxy the retrieval the same way as you do the upload, but then you're severely limited in the size of the objects that you can handle (as well for upload as download) – stijndepestel Aug 18 '21 at 09:13
0

I know I am bit late here, but I wanted to give my opinion in case someone has the same problems. Your mobile app should communicate with a server app (backend app) for authentication and authorization. let's say you are deploying your server app on AWS VPC. Now, it's simple to manage the files access by creating a policy which allow just your server app (IP, or VPC) to access the bucket. the authorization part will be managed on your application.