AWS Cloudfront SetCookie in PHP - php

I am trying to set a cookie to view private content from AWS Cloudfront
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html
They give an example cookie header:
Set-Cookie: Domain=d111111abcdef8.cloudfront.net; Path=/; Secure; HttpOnly; CloudFront-Key-Pair-Id=APKA9ONS7QCOWEXAMPLE
I created the following php code
setcookie (
'CloudFront-Key-Pair Id',
'MYID',
0,
'/',
'mycloudfrontsub.cloudfront.net',
true,
true
);
But the cookie is not set. The cookie is only set if I take out the domain name.
I think this is due to calling the setcookie in a script after session_start. I tried adding this, but it's required before session_start()
session_set_cookie_params(0, '/', 'duvoxso6rm38g.cloudfront.net);
Do I need to do something like this?
//close local session, then open new one for aws
$id=SID;
session_write_close();
session_set_cookie_params(0, '/', 'mysub.cloudfront.net');
session_start();
setcookie(...);
session_write_close();
session_set_cookie_params(0, '/', 'originaldomain.com');
session_start();

The cookies do not show up in the browser because you send a cookie for a domain A from domain B. That is silently ignored by the browsers for security reasons. This is a browser feature not a PHP thing.
If you want to use signed cookies with CloudFront you need to use a CNAME for the CloudFront distribution that is a subdomain of you PHP server domain. A more detailed answer can be found under: https://mnm.at/markus/2015/04/05/serving-private-content-through-cloudfront-using-signed-cookies/
In short: assume you want to use the domain example.com. You serve the PHP files under www.example.com. Then you can use the CNAME media.example.com for the d111111abcdef8.cloudfront.net. To send the cookies from the PHP side to the CloudFront Server you need to use the domain example.com in the Cookie.
The referenced site does also notice that you should use the PHP function header() to send the cookie, not setcookie(). This is because the setcookie function does some encoding that ruins the singing parameter created with the functions mentioned on the site.

Related

Does php send a cookie to localhost with HTTP when session_start() with cookie_secure equal to true?

If I start a session like below for a server and a localhost client try to request the server via HTTP, does it response with the session cookie?
or must it go through HTTPS?
I read the doc and it did say only through HTTPS, but I wonder if localhost is an exception.
session_start([
'cookie_secure' => true
]);
Yes, it does:
If you try this in a browser, you'll also see a warning saying that the cookie was rejected.
This makes sense because PHP has no control on the entire communication channel and it's possible that the end-user is connecting to a secure proxy that redirects internally to a non-encrypted HTTP server.

Set-Cookie header not creating cookie in test environment

I have a local testing application mimicking the host test.mywebsite.com on port 4200.
It makes a call to api.test.mywebsite.com (also locally hosted) to /login
The request passes, the server returns 200 and some information, and along with it it sets this header which I see in the response headers:
Set-Cookie: refreshToken={JWT here}; expires=Sun, 23-May-2021 20:38:32 GMT; Max-Age=1296000; path=/; domain=.test.mywebsite.com; HttpOnly
This doesn't get stored in my browser (either Chrome or Firefox) and I'm trying to figure out why.
Here's some more information about my setup if needed:
Angular server using ng serve --host=test.mywebsite.com to get the test frontend up on http://test.mywebsite.com:4200
Kubernetes backend running on localhost (with my hosts file redirecting api.test.mywebsite.com to 127.0.0.1) which directs the request to a PHP pod that creates the cookie using this code:
setcookie(
"refreshToken", // name
$refreshJWT->token, // token
$refreshJWT->expiration, // expires in 15 days
'/', // path
".".$refreshJWT->domain, // domain
($refreshJWT->environmentType === "test") ? false : true, // security
true // httponly
);
I fear it's something painfully simple or an oversight somewhere, but can't for the life of me find out what. The only thing I can think of would be the port not matching with the cookie host, but as far as I know cookie domains are port-agnostic. I've tried adding :4200 to the end of the cookie domain anyway and still have the same problem.
Update: setcookie() returns true, so there's no output previous to setting the header.
Update2: I deployed it to a staging server and the problem still occurs despite no DNS trickery or proxies going on.
Update3: I've narrowed it down to a combination of my api server's Access-Control-Allow-Origin header, and my JS' use of withCredentials
My Access-Control-Allow-Origin is set to *. If I send the request withCredentials as false, it returns the body to the JS but refuses the cookie. If I set withCredentials to true, it sets the cookie but refuses to allow the JS to read the body.
I found out the reason, for anyone who may be stumbling on this:
The first problems was while my requests were going through and returning 200, the cookie was not being set because I didn't agree to receive a cookie on the frontend. To agree to cookies on the frontend, I had to use withCredentials.
The second problem was on the backend, I didn't explicitly send the header Access-Control-Allow-Credentials This would allow both front and backend to agree to a cookie exchange.
The third problem was my backend had a wildcard set for Access-Control-Allow-Origin, which my browser requires to match the current host exactly if withCredentials is used.
It makes a call to api.test.mywebsite.com
...
domain=.test.mywebsite.com
These need to be the same hostname

Session not persisting on bare IP address website 111.222.333.444:5566

The same PHP script I'm using works fine with sessions on a domain website like example.com but not so when it's uploaded and accessed on a bare IP address website with an arbitrary HTTP port number like this:
111.222.333.444:5566
Variables can be set in $_SESSION which is accessible in the same PHP request but they are gone with the next page load.
Tried this:
session_set_cookie_params(
0,
'/',
'111.222.333.444:5566'
);
session_start();
But it's not working. Also checked phpinfo() and the bare IP site's session is enabled. My browser does support cookie when both of the tests are run.
This is weird. What could be wrong here? Is PHP session meant to not persist on bare IP site with exotic HTTP port?
One of the requirements for cookies is:
The string is a host name (i.e., not an IP address).
You can't associate a cookie with an IP address, only with a hostname.
PHP sessions depend on session cookies to work.

problem with setting a cookieless domain

Here is the header from firebug that shows the scope of the PHP Session cookie:
Set-Cookie PHPSESSID=f0e2dfe56cc78be718c8154ac80d1ae2; path=/; domain=pix-all.com
But still the PHP Session cookie is been sent for any requests to static.pix-all.com
Cookie PHPSESSID=f0e2dfe56cc78be718c8154ac80d1ae2;
What could be the problem?
If the cookie is set for the domain pix-all.com, then it will always be sent in requests to static.pix-all.com because static.pix-all.com is a subdomain of pix-all.com
So what is the problem? You're having issues because the cookie works as it's supposed to?

Cross Server Cookies, PHP

We have 2 web servers, one secure and one normal.
Is it possible to set a cookie like this
setcookie("basket[id]", $newID, time()+60*60*24, "/", SITE_URL, 0, true);
setcookie("basket[id]", $newID, time()+60*60*24, "/", SECURE_SITE_URL, 1, false);
Where
SITE_URL = www.sitename.com
SECURE_SITE_URL = xxxxx.securesitename.com
Kyle
Set Cookie
With setcookie you can set the domain parameter to indicate where the cookie is available. To make the cookie available on all subdomains of example.com then you'd set it to '.example.com'. The . is not required but makes it compatible with more browsers.
As long as your servers are referred to with different sub-domains, you can set your cookies accordingly.
Secure parameter
Secure, indicates that the cookie should only be transmitted over a secure HTTPS connection from the client.
Setting a Cookie on a different domain
A server cannot set a cookie for a domain that it isn't a member of.
The server issuing the cookie must be a member of the domain that it tries to set in the cookie. That is, a server called www.myserver.com cannot set a cookie for the domain www.yourserver.com.
How Double Click do it
One exception to the rule is ad agency Double click. Who manage to add cookies to your PC without you visiting the specific web site by packaging cookies with image requests when they are loaded from their servers onto other peoples web sites.
You cannot set a cookie for a domain other than the current or a superset of it (like example.com is a superset of foo.example.com and bar.example.com). That means the second Set-Cookie will get rejected by the browser.
One solution is to use a subdomain of your main domain for your secure domain, like secure.example.com. Then a cookie set for .example.com would be available at www.example.com as well as at secure.example.com.

Categories