I am generating a Pre Signed URL to allow users to download files from an S3 Bucket. I am generating the URL's via the PHP SDK using the following code:
public static function get_content_link( $bucket, $key ) {
//check response code from AWS
require_once 'aws/aws-autoloader.php';
$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'eu-west-1',
'credentials' => [
'key' => 'MY-KEY',
'secret' => 'MY-SECRET',
],
]);
$cmd = $s3->getCommand('GetObject', [
'Bucket' => $bucket,
'Key' => $key
]);
$request = $s3->createPresignedRequest($cmd, '+500 minutes');
// Get the actual presigned-url
$presignedUrl = (string) $request->getUri();
return $presignedUrl;
}
The URLs are being returned as expected, for example:
https://s3-eu-west-1.amazonaws.com/MY-BUCKET-NAME/product/3166_1480009917388.mov?x-amz-content-sha256=unsigned-payload&x-amz-algorithm=aws4-hmac-sha256&x-amz-credential=akiaiqrmkn276hcpjkaq%2f20161127%2feu-west-1%2fs3%2faws4_request&x-amz-date=20161127t145603z&x-amz-signedheaders=host&x-amz-expires=30000&x-amz-signature=98eaef504f053ca56908ac49c6539c4a8b8e250d7d3a4a12460f4a806ec41c19
When I try to open any of the returned links in the browser I am getting an access denied error from S3:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>A37839BB23186F72</RequestId>
<HostId>
yvKTN+CN1TTNk2tqoxxm3MPOGTUSMaRYtbbEFeCzGP7ou5IYf37Z9uBESwUQWDIUR1GUuPbZyuM=
</HostId>
</Error>
The files that I want to provide access to are in a bucket which contains folders allowing public access, by the folder I am trying to access is private (called /product/). Our bucket policy looks like this:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicReadProxies",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::MY-BUCKET-NAME/proxies*"
},
{
"Sid": "AllowPublicReadThumbs",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::MY-BUCKET-NAME/thumbs*"
}
]
}
It is my understanding that the purpose of creating a Pre Signed URL is to allow unauthenticated users temporary access to protected files without having to modify the bucket or folder permissions.
Has anyone got any ideas as to what I have missed or done wrong?
Thanks!
Many thanks to @Michael-sqlbot for figuring this out for me.
It turns out I was forcing the entire URL to be lowercase when outputting the pre signed URL to the page, so AWS was returning an Access Denied error due to the fact that the resource technically didn't exist.
If you're getting this error, also make sure you are not doing a GET request to the presigned url, instead of a POST request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With