2

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?

1
  • 2
    According to the documentation you can use a wildcard * "anywhere in the string" when generating a signed URL using a custom policy (not a canned policy) which should allow something like https://example.com/images/funny/cat.png?size=* in the policy document to authorize any matching request. Have you tried that approach? Commented Mar 10, 2019 at 3:42

2 Answers 2

1

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 *.

Sign up to request clarification or add additional context in comments.

1 Comment

I had exactly the same problem. thanks for the hint!
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.