Reputation: 61
I am setting up a HLS streaming service through cloudfront and implementing several security measures for content protection. I have successfully made it work under http, I can stream video and watch it in my website with a lot of content protection security measures. For more details on how I managed to make it work for http you can consult it in a post I made in drupal.org about secure hls streaming.
But now I need to add https to the formula because some encryption keys for hls encrypted segments are being transmitted, but I am having problems. Now I am working to add https to the formula. I have added a certificate to my site and I have added a different certificate in cludfront because my certificate is not a wildcard one.
My site certificate works for subdomain.mydomain.com
My cloudfront certificate is for *.mydomain.com
My cloudfront distribution has a cname of cdn.mydomain.com
When I create the cookie I set the secure parameter to true in the call (6th parameter after domain):
setcookie($name, $value, strtotime('+1 hour'), "/", ".mydomain.com", true, true);
But when I try to access some test data in my site
if (readfile('https://cdn.mydomain.com/privacy_test.txt')==0)
print "Error in cdn access";
I don't see the contents of the file in my website, but the error message.
So it seems I need more things to do to make cloudfront aws signed cookies work under https. Any help?
Upvotes: 6
Views: 1859
Reputation: 469
Simply setting the $secure
parameter of setcookie()
does not create a signed cookie. The process to create a signed cookie is a bit complicated. First, review Using Signed Cookies, specifically the Canned and Custom policy sections. You will need to familiarize yourself with creating a Policy, base64encoding that Policy and creating a Signature from the encoded policy.
Leveraging the code examples outlined in here, I then use the following code in a few of my applications to set the cookies:
public static function getCustomSignedCookies()
{
$domain = '.' . explode('.', apache_request_headers()['Host'], 2)[1];
$dt = new DateTime();
$dt->add(new DateInterval('P1Y')); // 1 year
$expires = $dt->getTimestamp();
$url = Config::get('cloudfront_url') . '/*';
$policy = self::getCustomPolicy($url, $expires);
$encodedPolicy = self::url_safe_base64_encode($policy);
$signature = self::getSignature($policy);
$cookies = [
[
'name' => 'CloudFront-Policy'
, 'value' => $encodedPolicy
, 'expires' => $expires
, 'path' => '/'
, 'domain' => $domain
, 'secure' => true
, 'httpOnly' => true
],
[
'name' => 'CloudFront-Signature'
, 'value' => $signature
, 'expires' => $expires
, 'path' => '/'
, 'domain' => $domain
, 'secure' => true
, 'httpOnly' => true
],
[
'name' => 'CloudFront-Key-Pair-Id'
, 'value' => self::$keyPair
, 'expires' => $expires
, 'path' => '/'
, 'domain' => $domain
, 'secure' => true
, 'httpOnly' => true
]
];
return $cookies;
}
public static function setCloudFrontCookies()
{
ob_start();
foreach (self::getCustomSignedCookies() as $cookie)
{
setcookie
(
$cookie['name']
, $cookie['value']
, $cookie['expires']
, $cookie['path']
, $cookie['domain']
, $cookie['secure']
, $cookie['httpOnly']
);
}
ob_end_flush();
}
Upvotes: 2