I was working on jsonP to send data from a cookie, from a domain A to a domain B. It works well, but my question is not here. I just realize that if I only put a script tag on my domain B pointing to my domain A, all the cookies of my domain A are set on my domain B.
Example: I put this tag on my domain B :
<script src="http://mydomainA.com/"></script>
Only with that, all the cookies of my domain A are set on my domain B.
My question is, is it normal? I thought cookie need some hacks to be cross domain, but i didn't think it was that easy.
Sorry for my bad english, and apologize if my question is stupid or if it has been asked before.
Thanks in advance.
Cookies are simply headers in HTTP requests. When the browser requests
GET /foo
Host: a.com
it receives a HTML document, which contains a <script> tag hosted on another domain. So it fires another request:
GET /script.js
Host: b.com
Cookie: foobarbaz
and it can certainly append cookies for domain b.com, if any. This means that the last time the browser contacted b.com, the HTTP response contained an header like
...
Set-Cookie: foobarbaz
...
and so subsequent requests to the same domain will maintain the session. When the browser requests another resource to a.com such as
GET /bar.jpeg
Host: a.com
the cookie foobarbaz set by b.com will not be sent along with the request, so the scripts on a.com don't have access to data from b.com.
Related
I have a domain with multiple subdomains and for each subdomain, there is a session cookie set from the main domain. All the session cookies are set with the domain as ".mainDomain.com" and used in specific auth related api calls. Also I have cookies specific for each subdomain with domain set as "subdomain.mainDomain.com".
I want to send fetch calls with only the cookies set from the subdomain and not the main domain.
Is there any way to achieve this?
Or, if there is a way to send a set of handpicked cookies in request header while ignoring the browser cookies like
Header: { Cookie: "test=test;" // this doesn't work now }
I know if the domain is .mainDomain.com, then *.mainDomain.com and mainDomain.com can access it. I was wondering if there is any way to make fetch ignore this.
I tried to set the cookie in header for the fetch call, but since Cookie is a forbidden header name it is not working, obviously. The only way I can think of is remove the cookies from mainDomain before each api call and set it back after. But I don't want to do it.
When I send a response from my server after authentication, I'm setting an authentication token cookie in the client's browser using this header:
Set-Cookie:mysite_auth=encodedJwtHere.JustPretend; SameSite=lax; domain=subdomain.mydomain.com; HTTPOnly; Max-Age=600; Secure; path=/
However, when I open EditThisCookie in Chrome, I can see that the domain is being set to .subdomain.mydomain.com automatically.
From what I thought I understood, this shouldn't be an issue. When I request https://subdomain.mydomain.com in the browser, the cookie is being sent.
My issue happens when I try to make a CORS request. I'm developing a javascript app and serving it on localhost. When I make an AJAX call to https://subdomain.mydomain.com, the cookie is not sent.
I have all of the proper headers set on the response:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, *
Access-Control-Allow-Origin:*
I have the {withCredentials:true} config on my request.
If I open https://subdomain.mydomain.com in the browser, then with EditThisCookie, I remove the prefix dot, I.E. I change .subdomain.mydomain.com to subdomain.mydomain.com, suddenly my AJAX calls from localhost work. The cookie is sent with the request.
So my question is, first of all, why is the cookie not being sent when there is a prefix dot, and is there a way to resolve this issue without manually editing the domain every time my cookie is refreshed?
If you're sending credentials, you can't respond with Access-Control-Allow-Origin:* - you must respond with a value that EXACTLY mirrors the Origin request header, e.g. Access-Control-Allow-Origin: {value-of-Origin-Header}.
In your case, that would presumably be Access-Control-Allow-Origin: https://subdomain.mydomain.com. Best not to hard-code it though - just mirror back Origin value.
Let's say I have domain a.com and b.com, and I own both domains. There's a page on b.com called setcookie.aspx and in the server code, it sets a cookie under the b.com domain.
I want to make an HTTP get request to b.com/setcookie.aspx from a.com (b.com is already allowing CORS requests from a.com) like so:
$.get('http://www.b.com/setcookie.aspx');
For some reason, the cookie is not being set. However, if I put the URL in a hidden image tag:
<img src="http://www.b.com/setcookie.aspx" style="display: none;" />
Then it works. Any idea why the AJAX request doesn't set the cookie?
You need to make 2 changes.
On a.com
As pointed out by #Jaromanda X in the comments, you need to set withCredentials=true in your $.get request. Cross-domain cookies are not allowed to be set by browsers unless you do this. Read this XMLHttpRequest.withCredentials
On b.com
When a cookie is to be set from the server side, it will send a header of the form:
set-cookie: key=val; expires=Fri, 24-Jan-20 10:29:58 GMT; path=/; domain=example.com; HttpOnly; SameSite=Lax
Notice the SameSite=Lax flag. This prevents the browser from setting cookie across domains.
From the Mozilla Set-Cookie docs
Asserts that a cookie must not be sent with cross-origin requests,
providing some protection against cross-site request forgery attacks
You need to disable this flag. This will depend on your backend platform. I use Django and for me it was just changing 1 setting SESSION_COOKIE_SAMESITE. This allows me to set the session id cookie to be set via a cross-domain AJAX request.
Once you do these 2 changes, the cross-domain cookie will be set. However, make sure to have enough CORS and CSRF checks to ensure the request comes from trusted origins.
For example, the first search result on this page leads to the older SO question, with the following HTTP request:
GET /questions/4402502/how-does-google-set-the-http-referrer-when-someone-clicks-on-a-search-result-lin HTTP/1.1
Host stackoverflow.com
Referer https://www.google.ru
Note, that:
Only the domain is included in the Referer header, no query string.
Google is open via HTTPS, while SO is open via plain HTTP - nevertherless, the Referer header is sent by the browser.
There are no server-side redirects involved, the first HTTP query to open after the click is to the target site.
The question is, how do they achieve this?
Google makes use of Referrer Policy.
They include the meta tag in the page:
<meta name="referrer" content="origin">
This tells browsers to use "Origin Only" policy, that is, to send domain only information in the Referrer header in any subsequent request.
finding the URL without server activity and
without the func() document.referrer.??
it should be secured.
Over secure connections no referrer header is sent.
Clients SHOULD NOT include a Referer header field in a (non-secure)
HTTP request if the referring page was transferred with a secure
protocol.
Source: http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html (about a third of the way down the page)