My goal is to issue a GET request, including a cookie, from javascript which will be hosted on multiple domains, to an API on a common domain. If the cookie is missing, I create one and return it for use in subsequent requests.
Initially I encountered an issue with the browser refusing to allow a jQuery get to a domain different to the page's domain, which I know is to do with CSRF protection.
I tried dozens of different ways to setup CORS with my DotNet Core 2.1 API project, such as described in this question: How to enable CORS in ASP.NET Core, and on numerous blogs like this one: https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas
Although I was able to get rid of the CSRF problem, cookies were never being delivered in the request, so every time the server would create a new one and send it back, the browser would either not retain it or not send it with subsequent requests to the server.
Then I discovered that if I add the SameSite = SameSiteMode.None
line to my cookie creation, it works:
[HttpGet("[action]")]
public async Task<IActionResult> Track()
{
const string cookieName = "TrackingCookie";
string uniqueId = Request.Cookies[cookieName];
if (string.IsNullOrWhiteSpace(uniqueId))
{
uniqueId = "123"; // debug - this would be generated
Response.Cookies.Append(cookieName, uniqueId, new CookieOptions
{
SameSite = SameSiteMode.None,
Expires = DateTimeOffset.UtcNow.AddSeconds(30) // debug - short duration for testing only
});
logger.LogWarning($"Cookie missing, so created it with unique id '{uniqueId}'.");
return Created(Url.Action(), $"Created unique id '{uniqueId}'.");
}
logger.LogWarning($"Cookie found, unique id '{uniqueId}' present.");
}
However, I also discovered that it still works if I remove literally every CORS-related declaration from my Startup.cs file. It still works if I completely remove:
services.AddCors(options => options.AddPolicy("MyPolicy", builder =>
{
builder.WithOrigins("http://markscoolsite.com:5000")
.AllowAnyMethod()
.AllowAnyHeader();
}));
and:
app.UseCors("MyPolicy");
Furthermore, the cookie works regardless of what domain I put it on, so it is clearly not acknowledging the WithOrigins(...)
directive.
For reference, this is my javascript code:
$(function () {
$.ajaxSetup({ xhrFields: { withCredentials: true } });
$.get('http://localhost:5000/api/tracking/track')
.done(console.log);
});
- Why does this cookie work for any origin without needing any of the CORS additions to Startup.cs that are described in the linked question and countless others? Have I completely misunderstood what CORS is for in MVC6?
- How can I limit my cookie to only work from the sites I specify? I'm concerned the way I've got it working is probably not very secure.