So I have a private CDN (can't access data through S3, only by signed URL & cookies) using CloudFront that holds some files for a web application.
One of the pages on my site displays an image whose source lives on the cdn.
<img src="cdn.example.com/images/file.jpg">
Now when I generate a signed URL on the server I can just pass it to the client and set it as source...Easy
But when I try to do the same thing using signed cookies I run into 2 problems:
I'm using node, express, and cookie-parser. I'm fairly new to this stuff so any help is appreciated
If you want to receive cookies at your origin but you don't want CloudFront to cache the Set-Cookie headers in your origin's responses, configure your origin to add a Cache-Control header with a no-cache directive that specifies Set-Cookie as a field name. For example: Cache-Control: no-cache="Set-Cookie" .
CloudFront signed cookies allow you to control who can access your content when you don't want to change your current URLs or when you want to provide access to multiple restricted files, for example, all of the files in the subscribers' area of a website.
Have you checked that the domain for the cookie is the same or a subdomain of the CloudFront CDN?
The cookie will be included in the request to the CloudFront distribution only if it is coming from a related domain. For example, if you are testing locally using "localhost" that won't work as the cookie domain is "localhost" but the signed cookie domain is "cdn.example.com".
To ensure that the domain is correct:
Set up a CNAME for the CloudFront Distribution e.g. http://cdn.example.com
Make sure the signed cookie has the correct
domain e.g. domain:'*.example.com'
will match against the domain.
There's a good article here: https://www.spacevatican.org/2015/5/1/using-cloudfront-signed-cookies/
There's also a good node module for creating signed cookies: https://github.com/jasonsims/aws-cloudfront-sign
Using this module you would do something like:
const options = {
keypairId: YOUR_ACCESS_ID,
privateKeyPath: PATH_TO_PEM_FILE
};
const signedCookies = cf.getSignedCookies("http://cdn.example.com/*", options);
for (const cookieId in signedCookies) {
res.cookie(cookieId, signedCookies[cookieId], {domain: ".example.com"});
}
Note the way I set the domain. If not explicitly set it will default to the one that made the request, which is probably not what you want.
Last thing, to test this locally, I set up port-forwarding on my home network and created a CNAME in GoDaddy to point to my home IP e.g. "test.example.com". I then used "http://test.example.com" instead of "http://localhost". This created a cookie with the subdomain "test.example.com". Finally, I created another CNAME in GoDaddy called "cdn.example.com", pointing it to the CloudFront URL. I used the wildcard domain in my signed cookie, ".example.com" and because I now have the signed cookie on the same domain "example.com" it's passed to CloudFront and boom we have liftoff!
For those trying to access a protected resource in CloudFront from a different domain you can not set the cookies cross domain so you're limited to using Signed URLs instead. However you can use javascript on the CloudFront site to use the parameters in the Signed URL to create a Signed Cookie directly in CloudFront. I put together a simple JS script that does just that.
aws-signed-cookie-from-signed-url.js
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With