Search code examples
javascriptasp.netcookiescross-domainsamesite

How do I prevent the "cookie associated with a cross-site resource set without SameSite attribute" warning when making AJAX Cross origin requests?


So, I have two sites http://localhost/ and http://3rdPartyLocallyHostedAPI/ (Not the real names) - both are local intranet sites, and due to the nature of 3rdPartyLocallyHostedAPI being it's namesake, localhost is having to make CORS requests to it.

These requests are working fine, data is returned or can be posted to 3rdPartyLocallyHostedAPI as would be expected, however this warning is being shown:

A cookie associated with a cross-site resource at http://3rdPartyLocallyHostedAPI/ was set without the SameSite attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.

Now, I've looked at multiple answers such as this one, this one and this one which state that the SameSite attribute needs to be set on the server, which doesn't make any sense as the two cookies it's taking issue with (ss-pid and ss-id) are set in the request, not returned in the response? This has confused me, as I can't figure out how or where to make a change to ensure the SameSite policy on these cookies is set to none or secure.

I think it's the jQuery that is performing the AJAX request that is at fault though:

// trimType and queryValue are determined elsewhere by some jQuery selections, their values are not important to the question being asked.
$.ajax({
    url: 'http://3rdPartyLocallyHostedAPI?q=' + trimType + '?q=' + queryValue + '&resultsOnly=true',
    data: {
        properties: (trimType === 'Record') ? 'Title,Number,RecordRecordType' : 'NameString'
    },
    xhrFields: {
        withCredentials: true
    },
    dataType: 'json'
}).done(function (data) {
    if (data.Results.length > 0) {
        $resultsPane.html('');
        for (var i = 0; i < data.Results.length; i++) {
            // Not relevant to the question being asked so removed, only some jQuery in here to display results on page.
        }
    } else {
        $resultsPane.html('<p class="py-1 pl-1 list-group-item text-muted">No Results found.</p>');
    }
}).fail(function () {
    $resultsPane.html('<p class="py-1 pl-1 list-group-item text-muted">No Results found.</p>');
});

When it doesn't have the withCredentials = true property set, and therefore is authenticating anonymously against the API (which only gives limited access, hence the need to pass windows credentials), the SameSite warning does not appear. Here is the request header:

GET /CMServiceAPIAuth/Location?q=%22SDC%20*%22&resultsOnly=true&properties=NameString HTTP/1.1
Host: serverName
Connection: keep-alive
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36
Origin: http://localhost:64505
Referer: http://localhost:64505/Home/DisplayRecord
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: ss-pid=OQtDrnmok62FvLlZPnZV; ss-id=cIaIcS3j0jmoouAaHHGT

The two cookies that chrome is having issues with are ss-pid and ss-id, there are no cookies being passed back by the response headers:

HTTP/1.1 200 OK
Cache-Control: private,no-cache
Content-Type: application/json; charset=utf-8
Vary: Accept
Server: Microsoft-IIS/8.5
X-Content-Type-Options: nosniff
X-Powered-By: ServiceStack/4.512 NET45 Win32NT/.NET
X-AspNet-Version: 4.0.30319
Access-Control-Allow-Origin: http://localhost:64505
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST,GET,OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Persistent-Auth: true
X-Powered-By: ASP.NET
Date: Mon, 27 Jul 2020 07:02:06 GMT
Content-Length: 1597

So, with all this in mind, can someone explain where I'm going wrong? Do I need to make changes to the jQuery AJAX to prevent this warning (and therefore prevent a future issue when the change the warning is alerting me about happens) - or, do I actually need to set an additional header on the server, I'm wondering if in the pre-flight OPTIONS request if it tries to figure out the SameSite setting for the request or something like that?

Via an IIS Module, I do have access to add additional headers to the response the server is sending, so if that is what is needed, I can do it - I just don't quite understand on which end the warning is being caused by and would appreciate any explanation people can provide.


Solution

  • Ok then, I think I've done enough research to figure out the issue I'm facing, so I'll answer my own question.

    So, one page that really helped me to actually understand what SameSite is about was this one, so to anyone else having issues with SameSite, take a read so that you understand the reason behind it and how it works.

    Having done some reading and seeing this answer to another post helped me to connect the dots. I deployed the web site I'm working on to an actual web server, and found that the following was the response header:

    HTTP/1.1 200 OK
    Cache-Control: private,no-cache
    Content-Type: application/json; charset=utf-8
    Vary: Accept
    Server: Microsoft-IIS/10.0
    X-Content-Type-Options: nosniff
    X-Powered-By: ServiceStack/4.512 NET45 Win32NT/.NET
    X-AspNet-Version: 4.0.30319
    Set-Cookie: ss-pid=0QyVIKf4edkAKd2h4be5; expires=Fri, 27-Jul-2040 09:58:39 GMT; path=/; HttpOnly
    Set-Cookie: ss-id=fmM1WQsDxXGfR8q9GL6e; path=/; HttpOnly
    Access-Control-Allow-Origin: http://server
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Methods: POST,GET,OPTIONS
    Access-Control-Allow-Headers: Content-Type, Authorization
    Persistent-Auth: true
    WWW-Authenticate: Negotiate oYG2MIGzoAMKAQChCwYJKoZIgvcSAQICooGeBIGbYIGYBgkqhkiG9xIBAgICAG+BiDCBhaADAgEFoQMCAQ+ieTB3oAMCARKicARusah2q1K2ACHwoq1n6DCNq5rx/HFdbK5sU9EohnxrRSpzmelskTTa9xmW8wgeUdwRNQCqMsD/dZ/pUjhdl2CVWjmFZZAfnKl6JEker+s79E9uFXThZZKnqfpqEgSvvqSYpp1KMkaYBYd1uf5mRyE=
    Date: Mon, 27 Jul 2020 09:58:40 GMT
    Content-Length: 1597
    

    There are two Set-Cookie headers being issued by the server to store values for ss-id and ss-pid. These cookies apparently stand for permanant session ID and session ID, and are issued by ASP.NET for tracking sessions. The browser does not accept and set these two cookies as they lack the SameSite=none setting and the Secure setting - these are the two cookies mentioned in the post above that I was talking about.

    So to fix this issue, first off I need to switch to using https for the API (and potentially the site itself) - which I have already done, and somehow figure out how to get the 3rd party API to set SameSite attributes in it's session related cookies.

    So for others who hopefully have complete control of your API's etc, you should just be able to set these attributes whenever you are creating/sending cookies in responses, and therefore send cookies from the site to other domains by setting SameSite=None and Secure.