Posted on under Laravel by Owen Conti.
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:
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:
The first thing we need to do is update the CloudFront origin settings to allow access to the S3 bucket:
Next, we need to tell the CloudFront distribution to accept signed requests.
In the first step, we selected "Yes, Update Bucket Policy". However, we should verify the policy was updated correctly:
1{ 2 "Version": "2008-10-17", 3 "Id": "PolicyForCloudFrontPrivateContent", 4 "Statement": [ 5 { 6 "Sid": "1", 7 "Effect": "Allow", 8 "Principal": { 9 "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXX"10 },11 "Action": "s3:GetObject",12 "Resource": "arn:aws:s3:::XXXXXXXX/*"13 }14 ]15}
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:
1AWS_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:
1composer require dreamonkey/laravel-cloudfront-url-signer
1<?php 2 3$cloudfrontUrl = config('filesystems.disks.s3.url') . '/' . $filepath; 4$signedUrl = CloudFrontUrlSigner::sign($cloudfrontUrl); 5 6// You can either return the signed URL as string... 7// return $signedUrl; 8 9// or redirect the user to the file via the signed URL10return redirect($signedUrl);
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
Hopefully you found this article useful! If you did, share it on X!
Found an issue with the article? Submit your edits against the repository.