Bryce Sampson
Bryce Sampson

Reputation: 33

AWS Cloudfront Signed Url with Unsigned Query Parameters

I'm trying to host images on s3 with cloudfront but I want the client to choose the size of the image when making the image request using query parameters.

I want to used signed url's so if a user has a signed url they can access that image in any size they want. The problem is, the image size query params have to be appended to the url during signing otherwise the appending of the size query params will result in the signature check not passing. Meaning if I want the image in two different sizes, I need to make two round trips to the my server to sign the url with the size parameters, then fetch the images from cloudfront. I want to avoid this.

Is there any way I could accomplish this?

Upvotes: 2

Views: 1886

Answers (2)

patrickd
patrickd

Reputation: 316

You can also add the asterisk at the end of the path (like this https://example.com/images/funny/cat.png*) to allow further optional parameters to be added.

Upvotes: 1

Bryce Sampson
Bryce Sampson

Reputation: 33

Sovled! Thanks to @Michael - sqlbot. By using a custom policy I can return any image dimensions I want including the original size using one signed url. In case anyone else has this issue here's how I did it:

My php code to generate the signed url:

public static function signedImageUrl($resource)
{

    // Build Url
    $url = self::CLOUDFRONT_BASE . ltrim($resource, '/') . '?w=*&h=*';

    // Create a CloudFront Client
    $client = new CloudFrontClient([
        'version' => '2014-11-06',
        'region' => 'us-east-2'
    ]);

    // Set up parameter values for the resource
    $expires = time() + 300;

    // Policy
    $policy = '{ 
    "Statement": [
        { 
            "Resource":"' . $url . '",
            "Condition":{ 
                "DateLessThan":{"AWS:EpochTime":' . $expires . '}
            } 
        }
    ] 
    }';

    // Create a signed URL for the resource using the canned policy
    $signedUrlCannedPolicy = $client->getSignedUrl([
        'url' => $url,
        'policy' => $policy,
        'private_key' => env('AWS_CLOUDFRONT_PRIVATE_KEY_PATH'),
        'key_pair_id' => env('AWS_CLOUDFRONT_KEY_PAIR_ID')
    ]);

    return $signedUrlCannedPolicy;
}

Where CLOUDFRONT_BASE is the .cloudfront.net/ domain for my cloudfront distribution, and $resource is the filename (e.g. my_profile_image.png)

At this point I get my signed image and can then modify the w and h query parameters on the client to my hearts content. My lambda function is fired on the cloudfront ViewerRequest event and will direct cloudfront to load either the image with specified dimensions, or to load the original image if w and h are both *.

Upvotes: 1

Related Questions