# Understanding CloudFront Access to S3: OAI vs OAC — My Personal Experiment

Hey everyone! 👋

When I’m working with an S3 + CloudFront setup, I noticed something that made me curious there are **two different ways** to let CloudFront access S3: **OAI (Origin Access Identity)** and the newer **OAC (Origin Access Control)**.

That got me wondering:

> Why are there two options? What’s the real difference?

To answer that, I decided to run a hands-on experiment and explore both approaches in detail.

Now that I’ve done it, I’m sharing my experience below including what I built, what I learned, and how you can try it too.

If you've ever been confused about when to use which or how they actually work in practice this post is for you!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749896667013/2821c6fa-d7b2-41a6-843e-676c8a1e59ab.gif align="center")

---

# 🤔 Wait, Why Are There Two Options Anyway?

At first glance, both OAI and OAC let CloudFront access private S3 content securely so naturally, I wondered:

> If both are doing the same thing, why did AWS introduce a new method?

Here’s the thing: **both OAI and OAC are used to let CloudFront securely access content from an S3 bucket**. So, you might think: “If the end result is the same, why is AWS pushing everyone toward OAC now?”

Let me break it down for you:

---

# 🔍 The Problem with Legacy OAI

With **OAI**, we create a special identity, and we update our S3 bucket policy to allow that OAI to access the bucket. Then, CloudFront uses that identity to fetch content from S3.

Seems straightforward, right?

> But here’s the issue:  
> **Any CloudFront distribution using that same OAI can access the bucket.**

So, imagine I use the same OAI for multiple CloudFront distributions now, *all of them* can read from that S3 bucket. There's **no way to limit it to just one CloudFront distribution**.

🎯 That’s a **security gap**.

---

# 🔐 Enter OAC (Origin Access Control)

To address this issue, AWS introduced **OAC**.

With OAC, we create an access control configuration and assign it **per CloudFront distribution**. Then, in the S3 bucket policy, we don’t just allow based on a shared OAI… instead, we use a condition like `AWS:SourceArn` to **only allow that exact CloudFront distribution** to access the S3 content.

So now, **only one specific CloudFront distribution** and no others can read from the bucket. That’s a huge win for security and best practices. 🚀

---

# ❓But wait… Why Can’t We Just Use `SourceArn` with OAI?

I had the same question at first!

The problem is: **OAI doesn’t include the CloudFront distribution’s identity when making the request to S3**.

It only signs the request using the OAI credentials, but there's no way for S3 to know **which distribution** is calling. That means even if you try to use `AWS:SourceArn` in the bucket policy, it won’t work with OAI because the request lacks that source context.

👉 **OAC solves this by including the distribution’s ARN in the signature**, allowing S3 to enforce precise, per-distribution policies.

So, while OAI gives S3 a kind of generic identity, OAC brings full context and secure granularity.

---

# 🛠️ What I Built

Okay now I believe you understand the difference **theoretically**.  
But let’s be real: theory alone isn’t enough.

So how do we *actually* see this difference in action?

No worries **I got you!** 😎

I wrote a Terraform script that will let you spin up a hands-on environment in seconds.

Here’s what it does:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749895709405/32bc21b0-9512-40a3-a959-f740fc9d03a5.png align="center")

#### **Scenario 1 – Using OAI (Legacy)**

* Creates **one S3 bucket** with a test file.
    
* Creates **two CloudFront distributions (A & B)** using the **same OAI**.
    
* The S3 bucket policy allows access to that OAI.
    
* Result: **both distributions can access the S3 content**, even though we didn’t restrict them individually and *that’s the core issue* with OAI.
    

#### **Scenario 2 – Using OAC (Modern Approach)**

* Same S3 bucket and test file.
    
* Creates **two new CloudFront distributions (C & D)** using **OAC**.
    
* The bucket policy uses `AWS:SourceArn` to allow access **only from CloudFront distribution C**.
    
* This means:  
    ✅ **CloudFront C can access the S3 content**  
    ❌ **CloudFront D cannot**, because it's not explicitly allowed in the S3 bucket policy.
    
* Result: Now we have **tight access control** only the specified distributions can access the content.
    

---

### 🤯 What I Learned

#### ✅ OAI (Origin Access Identity)

* Simple and familiar.
    
* Bucket policy just checks the OAI ARN.
    
* **BUT**: you can't restrict it to a specific distribution, so if you share the same OAI with multiple CloudFront distributions, all of them get access.
    

This was clear when I spun up two distributions (A and B) both could access the S3 content, even though the bucket policy didn’t mention their individual ARNs.

#### ✅ OAC (Origin Access Control)

* Modern approach supports sigv4 signing.
    
* You **must** use `origin_access_control_id` in CloudFront.
    
* The S3 policy can now restrict access to a **specific CloudFront distribution** using `AWS:SourceArn`.
    

When I enabled OAC, only the distributions C and D were created. The S3 bucket policy now allow the specific distribution can access its content.

---

### 🧪 Try It Yourself

I have written all the Terraform code you need, also included clear instructions in the [GitHub README](https://github.com/gerlynm/just-curious/blob/main/cloudfront/oai-oac/README.md). so, you can spin up the full environment in just a few commands.

👉 **Repository URL**:  
🔗 [gerlynm/just-curious](https://github.com/gerlynm/just-curious)

---

### 📌 Final Thoughts

If you're building something new go with **OAC**. It’s more secure and future ready. But **OAI** still works.

Hope this helps someone trying to understand the differences through actual practice, just like I did. Let me know if you’d like the full Terraform code or a breakdown of the policy structures!

Happy experimenting! ✨
