Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP/Amazon S3: Query string authentication sometimes fails

I created a simple file browser in PHP that links to the files through generation expiring query URLs. So for each access to a directory, a link to each file is generated that is valid for say 900 seconds.

I now have the problem that the generated signatures seem to fail sometimes. Which is strange, since I intentionally used external S3 libraries for generating the URLs and signatures.

In fact, I tried the following libraries to generate the signatures:

  • CloudFusion
  • S3 generator
  • Amazon S3 PHP class

The libraries internally use hash_hmac('sha256', ... or hash_hmac('sha1', ... - I also don't understand why differnet hash algorithms are used.

Since the problem is the same with all libraries, it could as well be in my URL generation code, which is straightforward though:

$bucket = "myBucket";
$filename = $object->Key;
$linksValidForSeconds = 900;
$url = $s3->get_object_url($bucket, $filename, $linksValidForSeconds);

Sp $bucket and $linksValidForSeconds are constant, $filename is e.g. "Media/Pictures/My Picture.png". But event for same variables, it sometimes works, soemtimes doesn't.

Any ideas?

Edit: Typo/Wrong constant variable name fixed (thanks)

like image 355
Tarnschaf Avatar asked Sep 20 '10 18:09

Tarnschaf


2 Answers

I found the problem and it had nothing to do with the code I mentioned. The generated URL is urlencode()'d and sent to another PHP script. There I use the URL to display an image from S3. I used urldecode() there to undo the changes but apparently this is not neccesary.

So each time the signature contains certain chars, the urldecode() would change them and corrupt it.

Sorry for omitting the actual problem code.

like image 137
Tarnschaf Avatar answered Oct 20 '22 09:10

Tarnschaf


The code the asker is using above is from the CloudFusion AWS PHP SDK. Here's the documentation for get_object_url(): get_object_url ( $bucket, $filename, [ $preauth = 0 ], [ $opt = null ] )

The problem in your code above is your $linksValidForSeconds variable.

Where: $preauth - integer | string (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with strtotime().

In other words, you are setting an expires time for 900 seconds after UNIX Epoch. I am honestly not sure how any links have worked using that library with your client code. If you are using the CloudFusion SDK, what you want to do is take the current UNIX time and add 900 seconds to that when passing in the parameter.

You seem to be confusing this with the Amazon S3 Class' getAuthenticatedURL method which takes the parameter integer $lifetime in seconds as you've used in your client code.

Be careful when using multiple libraries and swapping between them freely. Things tend to break that way.

like image 1
Josh Smith Avatar answered Oct 20 '22 08:10

Josh Smith