CloudObjects / Directory / Amazon Web Services Integration / PresignProvider V4
Sign in

PresignProvider V4

a phpmae:Class in Amazon Web Services Integration

Provides the capability to generate Presigned URLs for Amazon Webservices APIs using the signature version 4.

Public PHP Methods
  • get($url, $region = 'us-east-1', $expiry = 3600)

    Sign a URL for a GET request.

  • put($url, $region = 'us-east-1', $expiry = 3600)

    Sign a URL for a PUT request.

  • post($url, $region = 'us-east-1', $expiry = 3600)

    Sign a URL for a POST request.

Source Code
<?php

use ML\IRI\IRI;
use CloudObjects\PhpMAE\ConfigLoader;

/**
 * Implementation for coid://aws.3rd-party.co/PresignProvider/V4
 */
class PresignProvider {

    private $awsAccessKeyId;
    private $awsSecretAccessKey;
    
    public function __construct(ConfigLoader $config) {
        $priorities = [ 'callerClass', 'callerClass.namespace' ];
        $this->awsAccessKeyId = $config->get('coid://aws.3rd-party.co/accessKeyId', $priorities);
        $this->awsSecretAccessKey = $config->get('coid://aws.3rd-party.co/secretAccessKey', $priorities);
    
        if (!isset($this->awsAccessKeyId) || !isset($this->awsSecretAccessKey))
          throw new \Exception("AWS credentials required.");
    }

    private function sign($method, $url, $expiry = 3600, $service = 's3', $region = 'us-east-1') {
        $url = new IRI($url);

        $date = new \DateTime('UTC');
        $scope = $date->format('Ymd').'/'.$region.'/'.$service.'/aws4_request';

        $query = http_build_query([
            'X-Amz-Algorithm' => 'AWS4-HMAC-SHA256',
            'X-Amz-Credential' => $this->awsAccessKeyId.'/'.$scope,
            'X-Amz-Date' => $date->format('Ymd\THis\Z'),
            'X-Amz-Expires' => (int)$expiry,
            'X-Amz-SignedHeaders' => 'host'
        ]);

		// Prepare canonical request
		$canonicalRequest = [
			$method,
			str_replace('%2F','/', rawurlencode($url->getPath())),
            ($url->getQuery()!='' ? $url->getQuery().'&' : '').$query,
            'host:'.$url->getHost()
		];

		$canonicalRequest[] = '';
		$canonicalRequest[] = 'host';
		$canonicalRequest[] = 'UNSIGNED-PAYLOAD';

        // Create string to sign
		$string = implode("\n", [
			'AWS4-HMAC-SHA256',
			$date->format('Ymd\THis\Z'),
			$scope,
			hash('SHA256', implode("\n", $canonicalRequest))
        ]);

		// Create signature
		$kSecret = 'AWS4'.$this->awsSecretAccessKey;
		$kDate = hash_hmac('SHA256', $date->format('Ymd'), $kSecret, true);
		$kRegion = hash_hmac('SHA256', $region, $kDate, true);
		$kService = hash_hmac('SHA256', 's3', $kRegion, true);
		$kSigning = hash_hmac('SHA256', 'aws4_request', $kService, true);

		$signature = hash_hmac('SHA256', $string, $kSigning);

		return (string)$url.($url->getQuery()=='' ? '?' : '&')
            .$query.'&X-Amz-Signature='.$signature;
    }

    /**
     * Sign a URL for a GET request.
     */
    public function get($url, $region = 'us-east-1', $expiry = 3600) {
        return $this->sign('GET', $url, $expiry, 's3', $region);
    }

    /**
     * Sign a URL for a PUT request.
     */
    public function put($url, $region = 'us-east-1', $expiry = 3600) {
        return $this->sign('PUT', $url, $expiry, 's3', $region);
    }

    /**
     * Sign a URL for a POST request.
     */
    public function post($url, $region = 'us-east-1', $expiry = 3600) {
        return $this->sign('POST', $url, $expiry, 's3', $region);
    }

}
Meta
URI / COID
coid://aws.3rd-party.co/PresignProvider/V4 content_copy
Revision
3-bc30c5dbf60160b4a5ef8b99ff2eb2bb content_copy
Short ID
aws:PresignProvider/V4 content_copy
Reference URL
https://coid.link/aws.3rd-party.co/PresignProvider/V4 content_copy
Last updated
2021-04-22 11:26 (UTC)
Created at
2021-04-22 11:26 (UTC)