skip to Main Content

I have a question regarding using an AWS S3 presigned URL to download a file to a remote server. I was able to successfully create the presigned URLs for a zip file. If I type the presigned URL into the browser I can successfully download the zip file. However, I also need our users’ site to get that zip file, download it to their server and unzip it. So what I did was use PHP CURL and provided the presigned URL for the CURLOPT_URL parameter. However, when I do this the zip file is empty and I get an error message. Since I am using a presigned url it already has the required authorization & signature headers to download the file. My question is why doesn’t it work in PHP CURL but only in the browser? What am I not doing right here?

Example Presigned URL:
https://xxxxxxx-xxxxxxxxxx-xxxxxxx-231481972270.s3-accesspoint.us-east-1.amazonaws.com/serenity-pro/serenity-pro.zip?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIATLZLGSYXEHERUI4Z%2F20210913%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210913T042133Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=62ba2cb3d434f8643cd5099b74523234df46b3c9fdb0f5ab75d962c8ab4d0428

My Code:

// Download zip file
// The $download_url is the presigned URL I generated for the user
$ch = curl_init();
$fp = fopen($theme_zip_path, "w+");
curl_setopt_array($ch, array(
CURLOPT_URL => $download_url,
CURLOPT_TIMEOUT => 600,
CURLOPT_FILE => $fp
));
$contents = curl_exec($ch);
curl_close($ch);
fclose($fp);

Error Message:
InvalidRequest The authorization mechanism you have provided is not supported. Please use Signature Version 4

3

Answers


  1. Chosen as BEST ANSWER

    In case anyone is encountering the same issue the solution is to use CloudFront signed URLs.

    https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateURL_PHP.html

    // Create a CF signed URL
    use AwsCloudFrontCloudFrontClient;
    
    $resourceKey = $cloudfront_url;
    $expires = time() + 1800;
    $privateKey = 'YOURPRIVATEKEY.pem';
    $keyPairId = 'YOURKEYPAIRID';
    
    $cfClient = new AwsCloudFrontCloudFrontClient([
        'version' => 'latest',
        'region' => 'YOURREGION',
        'credentials' => $credentials
    ]);
    
    $download_url = $cfClient->getSignedUrl([
        'url' => $resourceKey,
        'expires' => $expires,
        'private_key' => $privateKey,
        'key_pair_id' => $keyPairId
    ]);
    

  2. if your url contains https then try adding this

    CURLOPT_SSL_VERIFYHOST

    CURLOPT_SSL_VERIFYPEER

    curl_setopt_array($ch, array(
    CURLOPT_URL => $download_url,
    
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_SSL_VERIFYPEER => false,
    
    CURLOPT_TIMEOUT => 600,
    CURLOPT_FILE => $fp
    ));
    
    
    Login or Signup to reply.
  3. curl
    ‘https://xxxxxxx-xxxxxxxxxx-xxxxxxx-231481972270.s3-accesspoint.us-east-1.amazonaws.com/serenity-pro/serenity-pro.zip?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIATLZLGSYXEHERUI4Z%2F20210913%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210913T042133Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=62ba2cb3d434f8643cd5099b74523234df46b3c9fdb0f5ab75d962c8ab4d0428’
    –output serenity-pro.zip

    1. Insert the URL within quotes
    2. add the option –output with file-name as destination
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search