Published under Laravel.
If you upload files to AWS S3 via your Laravel application, but want to restrict access to those files, you can do so using signed requests.
Here's what the flow looks like:
Upload a file to a protected (no public access) S3 bucket
User makes a request to your application for the file
Your application determines if the user is allowed to access the file
If the user is allowed access to the file, the application creates a signed URL for the file
The signed URL is returned to the user
The user uses the signed URL to access the file
For most use cases, it makes sense to put a CloudFront distribution in front of your S3 bucket which will distribute your files to various edge locations across the world. We'll walk through how we can setup a S3 bucket and CloudFront distribution with access available only through signed requests.
This article will assume you have the following already configured:
S3 bucket is setup with no public access
A CloudFront distribution is setup with the S3 bucket configured as the origin
You have a Laravel application with your AWS Access Key and Secret Key configured
You are able to upload files to your S3 bucket via your Laravel application
You have knowledge of AWS and can get around the AWS Console
The first thing we need to do is update the CloudFront origin settings to allow access to the S3 bucket:
Restrict Bucket Access: Yes
Origin Access Identity: Create a New Identity
Grant Read Permissions on Bucket: Yes, Update Bucket Policy (this will update the S3 bucket's policy for you)
Next, we need to tell the CloudFront distribution to accept signed requests.
Restrict Viewer Access: Yes
Trusted Signers: Self (Self means the current AWS account the CloudFront distribution belongs to)
In the first step, we selected "Yes, Update Bucket Policy". However, we should verify the policy was updated correctly:
Alright, that's all we need to do on the AWS side, now onto updating your application.
We need to tell our application where it can find our CloudFront distribution. Update your .env
file to include a variable for AWS_URL
. The value should be the domain name of your CloudFront distribution:
AWS_URL=https://XXXXX.cloudfront.net
There's an awesome package available on GitHub which takes care of all the heavy lifting: https://github.com/dreamonkey/laravel-cloudfront-url-signer
Install the package by running:
composer require dreamonkey/laravel-cloudfront-url-signer
By default, the CloudFrontUrlSigner::sign
method will generate a signed URL that is valid for 1 day. Check out the GitHub page to see the various options you can pass to the sign
method: https://github.com/dreamonkey/laravel-cloudfront-url-signer
Did you find this post useful? Let me know on Twitter! If you found an issue with the content, submit a pull request!
Subscribe to my newsletter to know when I publish more content in the future.