8

We have the following configuration: testing.parentdomain.com

When you access this domain and create a basket we create a cookie stored for the basket value. The cookie domain is set to .testing.parentdomain.com, it is Httponly and has a path of /

We have a subdomain to the above which would like to access the cookie. subdomain.testing.parentdomain.com
This sub domain makes a call to an endpoint on the parent domain such as: testing.parentdomain.com/basketData. This call is a GET request that returns JSON.

Issue
The issue is that the subdomain does not appear to send the cookie value when making the request and therefore we do not get the expected response.

Attempts
Looking at other questions we have tried CORS and credential changes.
As an additional note, we bundle the below JS with webpack/babel.
Our request is from AJAX as follows:

  $.ajax({
    url: url,
    type: 'GET',
    xhrFields: {
      withCredentials: true
    },
    crossDomain: true
  })

The server is setup with CORS for the subdomain and allow-crendtials. In the response we can see these are returned.
access-control-allow-credentials: true
access-control-allow-origin: subdomain from above

Is there any reason that the cookie is not sent with the request to the parent domain? We have logged out the cookies on the server side response and they are not there as we expect.

Request Headers

:authority: testing.parentdomain.com
:method: GET
:path: /basket/data/
:scheme: https
accept: /
accept-encoding: gzip, deflate, br
accept-language: en-GB,en;q=0.9,en-US;q=0.8
origin: https://subdomain.testing.parentdomain.com
referer: https://subdomain.testing.parentdomain.com/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36

Response Headers

access-control-allow-credentials: true
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD, OPTIONS
access-control-allow-origin: https://subdomain.testing.parentdomain.com
cache-control: no-cache, no-store
content-length: 2238
content-type: application/json; charset=utf-8
date: Tue, 03 Nov 2020 20:39:36 GMT
expires: -1
pragma: no-cache
server: Microsoft-IIS/10.0
set-cookie: AWSALB=N0bcThdgRFzrSfQVNIsffgsvY6T/y2Bp47RZJCueeSLOS7eEjo0AThiElXmww6fy2eynRyyt8gAB8di/Mqy1x+Ds8Ig1TumKkWnQiFvIkoELI/rEYYgyUxbEtUI4; Expires=Tue, 10 Nov 2020 20:39:36 GMT; Path=/
set-cookie: AWSALBCORS=N0bcThdgRFzrSfQVNIsffgsvY6T/y2Bp47RZJCueeSLOS7eEjo0AThiElXmww6fy2eynRyyt8gAB8di/Mqy1x+Ds8Ig1TumKkWnQiFvIkoELI/rEYYgyUxbEtUI4; Expires=Tue, 10 Nov 2020 20:39:36 GMT; Path=/; SameSite=None; Secure
status: 200
strict-transport-security: max-age=31536000;
vary: Origin
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-robots-tag: noindex
x-ua-compatible: IE=edge
x-xss-protection: 1; mode=block

StuartM
  • 6,943
  • 16
  • 76
  • 142
  • Server doesn't logs the cookie, ok. Have you checked if the cookie is set on the client browser? Have you inspected the GET request (from the client browser) to check if the cookie is in the headers? These checks would help to distinguish if the problem is sending the cookie to server or setting the cookie on the client. Probably you already did this check, could you please confirm? Thank you – Daniele Ricci Oct 11 '20 at 14:15
  • Yes, we've confirmed the cookie is set correctly. The cookie is not sent with the request and/or it is not received by the response. Yes we are logging out the request cookies on the server to be able to determine this – StuartM Oct 13 '20 at 12:33
  • It would be useful if you add http request and response with header as you can see in browser console. – Lety Oct 13 '20 at 13:54
  • I strongly agree with @Lety – Daniele Ricci Oct 13 '20 at 17:11
  • is it possible to leave only the parent domain on the cookie? – Liran Oct 15 '20 at 13:30
  • @DanieleRicci added the request and response headers from the browser when calling the GET – StuartM Nov 03 '20 at 20:46
  • you should show us the request/response generated from testing.parentdomain.com, as I can see, Origin is subdomain.testing.parentdomain.com so this is the request that doesn't send cookie, isn't it? – Lety Nov 04 '20 at 10:54
  • @Lety the above is the response and request info from the following. On the sub domain, calling an endpoint on the parent domain. To be clear the cookie is set already when accessing the parent domain and completely something. Then we go to the sub domain and call an end point on the parent domain but the cookie is not sent with the request – StuartM Nov 04 '20 at 23:07
  • to be sure that I understand: a request to testing.parentdomain.com should receive a response with cookie valid for all subdomain and domain (this is the request/response I would like to see). Then request to subdomain.testing.parentdomain.com doesn't send cookie previously set (this I guess are the request/response in your question). Is this right? If yes, could you please add the first request/response that set cookie? – Lety Nov 05 '20 at 12:53
  • Have you checked this answer? https://stackoverflow.com/questions/18492576/share-cookie-between-subdomain-and-domain#answer-23086139 – Chengmin Nov 05 '20 at 16:42

2 Answers2

6

Even if you are calling the main domain from a subdomain, this is considered a cross-origin request.

Quote from the RFC 6454 which qualifies the "Origin" term:

Q: Why use the fully qualified host name instead of just the "top-
level" domain?

A: Although the DNS has hierarchical delegation, the trust
relationships between host names vary by deployment. For example, at many educational institutions, students can host content at
https://example.edu/~student/, but that does not mean a document
authored by a student should be part of the same origin (i.e.,
inhabit the same protection domain) as a web application for managing grades hosted at https://grades.example.edu/.

So all of the things you did are indeed required to make it work:

  • access-control-allow-credentials: true
  • access-control-allow-origin: subdomain.testing.parentdomain.com (not a wildcard)
  • withCredentials: true in the request

The SameSite=None cookie attribute is not required in this case because a request from a subdomain to another subdomain of the same domain is considered "same site" (Source).

So just check that everything is correctly set, it should work as is.

Guerric P
  • 20,579
  • 2
  • 28
  • 66
  • I have changed the cookie to ensure it is Secure and SameSite=None and the same issue occurs. It seems the cookie is not sent with the request as when testing in Postman the GET works fine. I've added the Response/Request headers that are shown in Chrome when the request is made from the webpage for more information – StuartM Nov 03 '20 at 20:48
  • The websites/APIs are served over HTTPS? – Guerric P Nov 03 '20 at 22:03
  • Yes both served over https – StuartM Nov 04 '20 at 23:07
  • This was the most complete answer to the question. We added the required headers and the issue still occurred, however, this was caused by a mistake in our build process which meant the withCredentials was not being pushed into the built JS file. Once we added this, everything started to work as we expected. – StuartM Nov 09 '20 at 09:45
  • That was obviously some kind of silly mistake. Glad to know you finally made it! – Guerric P Nov 09 '20 at 09:58
  • It boiled down to missing ```&&``` from a build command, so yes a silly mistake... Got to love it! – StuartM Nov 11 '20 at 12:09
  • This answer is incorrect and a bit harmful: the cookie's `SameSite` attribute needs not be set to `None`, here. Why? Because, if the request originates from a subdomain of the target origin, then that request is considered _same-site_, and the `SameSite` attribute simply doesn't apply in such cases. Don't conflate _origin_ and _site_. See https://web.dev/same-site-same-origin/ and https://jub0bs.com/posts/2021-01-29-great-samesite-confusion/ – jub0bs Mar 28 '21 at 12:04
  • 1
    Thanks for pointing this out, I've edited and added the source – Guerric P Mar 28 '21 at 17:17
3

At beginning of your question you stated:

The cookie domain is set to .testing.parentdomain.com

but in the logged server response:

set-cookie: AWSALBCORS=N0bcThdgRFzrSfQVNIsffgsvY6T/y2Bp47RZJCueeSLOS7eEjo0AThiElXmww6fy2eynRyyt8gAB8di/Mqy1x+Ds8Ig1TumKkWnQiFvIkoELI/rEYYgyUxbEtUI4; Expires=Tue, 10 Nov 2020 20:39:36 GMT; Path=/; SameSite=None; Secure

the Domain=.testing.parentdomain.com; parameter is clearly missing.

I don't know which programming language you are using to set the cookie, but I strongly suggest you to check the call you use to set the cookie in your server response.

Daniele Ricci
  • 11,261
  • 1
  • 12
  • 32
  • Hi Daniel. The response from the server isn’t setting the cookie at this point the cookie is set before at some other stage which works fine. The cookie is set on the main domain then accessing from the sub domain we call an endpoint on the main domain, this is when the cookie is not sent – StuartM Nov 04 '20 at 23:05
  • Sorry @StuartM , the meaningful server response is the one which sets the cookie; you pasted a server response, I thought it was the one interested by this topic. Could you please share the server response which sets the cookie? The server response for the not working server call is useless to the purpose of solving this problem. – Daniele Ricci Nov 05 '20 at 08:23
  • It's an ASP.net backend and I can see that the cookie is set using editThisCookie. I can see the value is correct, the path is '/', the domain is '.testing.parentdomain.com', it is Secure and HTTPOnly. – StuartM Nov 05 '20 at 09:41
  • I'm sorry @StuartM , but without a) the dump of the client call used to set the cookie; b) the server response which sets the cookie - i.e. the server response to call a - ; c) the client request where the cookie is missing; I'm not able to help you – Daniele Ricci Nov 05 '20 at 14:39
  • By the way, checking the comments to your question @StuartM , I see Lety is asking the same dumps. – Daniele Ricci Nov 05 '20 at 15:01