How to prevent users from downloading files using S3 URLs

Β·

5 min read

How to prevent users from downloading files using S3 URLs

Suppose you have some assets for your platform which is being served to your customers in form of MP4 videos, PDFs, Etc.

I am assuming that data is important but not that sensitive, so this guide can be applicable for some specific use cases.

For ease of storing and to save some $$$, you chose to host your content on an AWS S3 bucket. That way you will also be utilizing AWS Global Infrastructure to make sure your assets are highly available.


Let's See, How You created Your Bucket -

Enter a suitable name for your bucket : 2021-10-16_18-24_1.png

Select an Encryption Method (To enable Encryption at Rest) : 2021-10-16_18-25_2.png

and leave everything as it is. Now proceed to create your new shiny bucket.

Create a folder for storing your assets, for example - course-videos + maintain the encryption scheme.

image.png

Upload the content, for now, I am uploading two videos, see below :

Image.png


Now, If you try to open your video in the browser using that S3 object URL, you'll see something like this:

image.png

and, that is totally fine, by default, your bucket is private and objects can not be accessed directly.

So now what? Ok, let's try to make the objects public and see what happens πŸ€”

image.png

image.png

Note - Click the image to enlarge


So If you were unable to understand, let me help you... Did you observe a checklist (aka Block public access (bucket settings)) while creating the bucket?

Which look something like this : 2021-10-16_18-25_1.png

So the thing is this checklist makes sure that all public access to the bucket and its objects is denied!

But for our use case, we need our assets to be public so our users can consume them.

So let's make our objects public now... For that go to your BUCKET > Permissions > Block public access (bucket settings)

image.png

Here, uncheck all the settings as I have shown in the image above.

Now, try again to make that folder public for our users.

2021-10-17_08-45.png

image.png

Woohoo! this time we were able to make our objects public.


I'd recommended you to go through this once to understand better what the Block public access settings offers.


Now let's add these URLs to your platform, I have created a Codepen where I will be referring these videos for demo purposes.

codepen.io/k4kratik/pen/NWvxowL?editors=1000

HTML Source : geeksforgeeks.org/html5-video


image.png

When you add the S3 Object URL to your platform, users are able to see the content, Great!

πŸ’‘For those who don't know, you can click on any object in S3 and from there you can copy the object URL.


The Problem

Wait what, you thought that was it? πŸ˜‚ No! Let's see what's the issue here.

ezgif-7-c4d1c5b01880.gif

Keeping objects as public does not mean anyone should be able to download these objects so easily! We made those objects public so our users on the Internet can access it for viewing, surely not for downloading! 😀


The Workaround

Yup! You read the title right! It is not a solution but a workaround that can be effective for most of the users who can try to download your content! 😜

So even before we start, I want to summarize what we are gonna do - We will make use of Bucket Policies, We will whitelist your platform's domain name so only your platform's webpages can access your assets.

Step-1: Change Block public access (bucket settings)

Again, Go back to Block public access (bucket settings) and keep the checklist as shown below :

In BUCKET > Permissions > Block public access (bucket settings)

image.png

You'll see that UI is little changes with these indications:

image.png

Don't worry we will fine-tune the access in a bit, Just stick to the guide!

Validation

Now when I check the webpage (In my case, it is Codepen) The video is not accessible anymore! πŸ˜₯

image.png

Step-2: Add the bucket policy to whitelist our domain

ℹ️ As you know from Step-1, our video was unable to play. let's resolve this.

For that go to your BUCKET > Permissions > Bucket policy and paste the below code.

⚠️ Make sure you are replacing kratik-blog-assets with your bucket name.

⚠️ For the value of the Key "aws:Referer", make sure you are adding your domain name(s).

{
    "Version": "2012-10-17",
    "Id": "http referer policy example",
    "Statement": [
        {
            "Sid": "Allow get requests originating from your domains only.",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::kratik-test/*",
            "Condition": {
                "StringLike": {
                    "aws:Referer": [
                        "https://codepen.io/*",
                        "https://cdpn.io/*"
                    ]
                }
            }
        }
    ]
}

It will look something like this:

image.png

Validation

Check the Codepen again and observe if something is different now.

image.png

Oh, Wow! Our video is able to play on our platform's Webpage.

ℹ️ As we created the above Bucket policy, it whitelisted our domain and allowed access.

Step-3: Testing the Download

Let's try again downloading our assets.

ezgif-2-9edf37a2f1d0.gif

🎊 πŸŽ‰ πŸ₯³

This is what we wanted right? Users can view your content but won't be able to download it.

isn't it cool?


Disclaimer

As I mentioned this is a workaround but not a 100% foolproof solution, technically advanced users can bypass this policy very easily, So if your data is really very very sensitive, my Suggestion is, Don't do this :)

For more sensitive content there are other methods available that require time and knowledge to set up but yeah, they will def fulfill your use case.

For example :


Drop Some Emojis if you find this useful. Or leave a comment.

Thanks for Reading! πŸ™‡β€β™‚οΈ


Wanna buy me a Coffee β˜• ?

buy-me-a-coffee.jpeg

Did you find this article valuable?

Support Kratik Jain by becoming a sponsor. Any amount is appreciated!

Β