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?
Related
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
I noticed something earlier today while inspecting cookies on some of my subdomains that surprised me a little. Although I have set PHP to use only secure cookies, they are nonetheless available using HTTP.
My root domain and most of my subdomains are HTTPS. In fact, they are essentially HTTPS only. I haven't enabled HSTS because I have subdomains that are HTTP only and do not support HTTPS. (Essentially, my domains are either HTTPS only or HTTP only, not both.) While navigating to these subdomains, I noticed the cookies set by the root domain show up in the browser developer tools, and are seemingly sent on requests to the server.
I'd prefer this not happen because a) it's insecure and b) the server handling these subdomains does squat with these cookies so sending them at all is an unnecessary risk that could compromise the main applications.
The weird thing is my cookies are already secure. All cookies are set like so:
setCookie("my_cookie", $cookieValue, $expires, '/', $domain, true, true);
At the top of my session manager, I also have:
session_set_cookie_params(3600, '/', '.example.com', true, true);
The last trues are secure and httpOnly. One would think this makes them HTTP-only:
HTTPS: Cookie with "Secure" will be returned only on HTTPS connections
Reading cookies via HTTPS that were set using HTTP
To ensure that the session cookie is sent only on HTTPS connections,
you can use the function session_set_cookie_params() before starting
the session: https://stackoverflow.com/a/6531754/6110631
A cookie with the Secure attribute is sent to the server only with an
encrypted request over the HTTPS protocol, never with unsecured HTTP,
and therefore can't easily be accessed by a man-in-the-middle
attacker. Insecure sites (with http: in the URL) can't set cookies
with the Secure attribute. However, do not assume that Secure prevents
all access to sensitive information in cookies; for example, it can be
read by someone with access to the client's hard disk.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies
But lo and behold, all cookies that I set on the root domain continue to be available on my HTTP-only subdomains. Using the developer tools, any changes with cookies in the root domain continue to be reflected on HTTP-only subdomains!
I intentionally set the cookie as .domain to make it available on all subdomains, since they all share session information and enable SSO (the HTTPS domains, that is). However, I would think that with the secure flag, this would still prevent the cookies from being available on HTTP-only subdomains. Does one of these parameters take precedence over another? (I would think secure would).
Why is this not working as intended? It seems that because the cookies are available, even though I have secure and httpOnly, the cookies could be stolen from an unencrypted HTTP connection. Is it that the cookies are not actually sent, but the browser (erroneously) displays them as present anyways, or is there a real security risk here?
The browser developer tools seems to make a distinction between displaying cookies that may be available on a domain and those that are actually sent in the request - that is to say, the developer tools will show cookies for a subdomain even if they are never sent on requests to the server.
Here's an example of a request to the root domain:
:authority: example.com
:method: GET
:path: /account
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cache-control: max-age=0
cookie: [cookies redacted]
dnt: 1
referer: [redacted]
upgrade-insecure-requests: 1
user-agent: [redacted]
Here's an example of a request to an HTTP-only subdomain:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
DNT: 1
Host: subdomain.example.com
If-Modified-Since: Wed, 27 May 2020 20:51:35 GMT
If-None-Match: "6c5-5a6a760afe782-gzip"
Upgrade-Insecure-Requests: 1
User-Agent: [redacted]
As one can see, cookies are not sent with the second request. However, if you examine the cookies on both domains in the browser, you can see the browser displays them regardless:
This can be a source of confusion, but examining the request headers shows that the browser does indeed refrain from sending the secure cookies on insecure requests.
I have some difficulties maintaining session on server request and response between initial server call and ajax call.
I am sending an ajax call after the server initial load to the same domain where am using sessions in both cases
The session cookie is not being set on server load (knowing that session_start() is called and the session has data) and it seems that it is being set twice on first ajax call:
Server Response of ajax call after page load
Set-Cookie: PHPSESSID=aef6668de2af148bcc3a3bd3de71f880; expires=Tue, 08-Mar-2016 07:38:43 GMT; path=/; domain=www.somedomain.com; secure; HttpOnly
PHPSESSID=aef6668de2af148bcc3a3bd3de71f880; expires=Tue, 08-Mar-2016 07:38:43 GMT; path=/
What actually triggers the server to send Set-Cookie header setting the session in cookie on server response?
Is it the session_start() or setting the $_SESSION with a given value at server side?
I know that session_set_cookie_params() also has this impact but can this in anyway create 2 consecutive set calls of the session if session_set_cookie_params() is called with session_start() in the same server response ?
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.
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.