I do not really understand the security behind AWS Cloudfront's OAI. The only thing it does is switch the bucket's domain. Instead of accessing the bucket with https://s3.amazonaws.com/[Bucket]/* it just switches it with your domain.

But again anyone can browse that bucket/folder knowing the CF domain.

Am I missing something? I know you can add a lambda function at the viewer request side to limit access from a certain app. But how can I prevent users from just trying random URLs. And I don't think its good practice to do authentication and to check if that user should have access to the resource on each request.

So what are good practices to restrict my users to only access the resources that they are allowed to view?

  • Hi Zaid, if the response below answered your question please upvote and accept it. That's the ServerFault's way to say thank you for the time and effort someone took to help you. Thanks!
    – MLu
    Nov 3, 2018 at 4:03
  • @MLu Sorry, while your answer is helpful, its not really what I am looking for. Hope you understand that I cannot currently accept it as THE answer just yet.
    – Zaid Amir
    Nov 4, 2018 at 9:41
  • no worries, however you may want to expand the question and/or comment why the answer is not sufficient. Otherwise you may not get the information you’re looking for.
    – MLu
    Nov 4, 2018 at 10:45

1 Answer 1


The purpose of Origin Access Identity is to prevent users from directly accessing the S3 Bucket. Instead they have to go through CloudFront; the origin S3 Bucket won't permit access to anyone accessing it directly.

Some reasons for enforcing access through CloudFront:

  • Caching at the edge (transfer from CloudFront is cheaper than from S3, and it's also closer to the user)
  • Authentication through Lambda at the edge
  • WAF enforcement

If you want to restrict access to individual objects within your bucket you should consider using Signed URLs - for example when the user logs in to your website you'll provide his documents through a pre-signed URLs, perhaps with some expiration limit.

The best practice is to have a separate bucket for public objects (e.g. website assets - images, css, html) and a different one for private objects that need authentication (e.g. customers' documents).

See here for S3 Pre-signed URL example


You can also use Lambda at the edge for authentication as described here: Use Lambda@Edge to Enhance Web Application Security

Which one to use depends on your usecase. The Pre-signed URL are shareable and can be time-limited, Lambda@Edge authenticated URLs won't be shareable and will require the user to login. Depends on what you need.

Hope that helps :)

  • Not sure I understand, at which level should the url be generated. and its not a website, its an app.
    – Zaid Amir
    Oct 29, 2018 at 10:16
  • My project is more complex that having public/private assets. I need a way to manage accessibility of assets for different users. For example, user A has access to assets 1,2 and 3 while user B has only access to assets 1 and 2. My other problem is that the app is accessing cloudfront directly so I'm not sure if I should let the app itself generate the signed URL as that will require having to store some AWS credentials within the app itself, nor I think it is wise to have some web micro service that creates the URLs as that would create a bottleneck.
    – Zaid Amir
    Oct 29, 2018 at 10:19
  • Where do you make the decision which user has access to what asset? On the server somewhere I assume. Well then when you decide that the user you are currently interacting with has access to certain assets you generate pre-signed URLs for those assets and send the URLs it to the user in some response. That response can have e.g. a list of his documents, each with a presigned URL for access.
    – MLu
    Oct 29, 2018 at 10:24
  • This signing can be done in Lambda, through API Gateway, on some heavier server-side app, etc.
    – MLu
    Oct 29, 2018 at 10:25
  • @ZaidAmir updated answer and added info on Lambda@Edge
    – MLu
    Oct 29, 2018 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.