5

I have a .net core webapi project set up to accept cross origin requests like so

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseCors(opts => opts
        .WithOrigins("https://fiddle.jshell.net")
        .AllowCredentials()
        .AllowAnyMethod()
        .AllowAnyHeader());

    app.UseHttpsRedirection();
    app.UseMvc();
}

This has a values controller with a GET method like so

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return Ok("cookies: " + string.Join(", ", HttpContext.Request.Cookies.Select(x => x.Key)));
    }
}

Now I am trying to send a fetch request from the browser like so

fetch('https://api.domain.com/api/values', { 
    headers: 
    { 
      'Content-Type': 'application/json' 
    }, 
    credentials: 'include', 
    mode: 'cors'
})
.then(function(resp){ 
    resp.text().then(function(data) { 
        console.log(data); 
  }) 
})
.catch(function(err){ 
    console.log(err) 
});

But this doesn't send the cookies from the page to the api. What am I missing here? I have tried all the solutions I could find about this including turning off third party cookies

Update

So, I still don't have an answer to why this doesn't work or any authoritative sources saying you can't send cookies cross-domain (or even one that says cross-origin != cross-domain).

What we found is that even cookies from sub-a.domian.com would not be sent to sub-b.domain.com. The way we 'solved' this is to create a cookie that is permanently bound to domain.com because those cookies are sent to sub-a.domain.com and sub-b.domain.com.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
reggaemahn
  • 6,272
  • 6
  • 34
  • 59
  • Cookies are bound to the domain under which they were issued. CORS doesn't change this. However it will allow you to write Javascript to copy the cookies from one domain to the other, assuming the aren't HttpOnly. – John Wu Jun 24 '19 at 07:05
  • @JohnWu Some of them are. I thought you could do that based on this https://github.com/github/fetch#sending-cookies for example – reggaemahn Jun 24 '19 at 07:13
  • I tested your code ,but it worked well and the response had the cookie-key values . It would be better if you could share the reproducible demo . – Xueli Chen Jun 25 '19 at 08:51
  • @XueliChen I'd be happy to, but how do I do it? I mean the backend. The code is same as what I have here. Btw, did you test this from the jsfiddle.net website? That's where I tried it from. – reggaemahn Jun 26 '19 at 01:14
  • @reggaemahn , I tested with a MVC project and Web API project based on your code. – Xueli Chen Jun 26 '19 at 01:38
  • So, you tried on different domains? This seems to work with loalhost and a different port but when you change the domain completely, it doesn't. For eg. if you host the webapi at api.something.com and call it from a UI hosted at somethingelse.com, somethingelse.com's cookies are not passed along with the request. – reggaemahn Jun 26 '19 at 03:31
  • @reggaemahn Have you tried AllowAnyOrigin() [https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.2#set-the-allowed-origins] ? Just to see if it works, i.e. if it is the cors problem in question – theCuriousOne Jul 01 '19 at 10:42
  • @theCuriousOne `AllowAnyOrigin()` won't work with `AllowCredentials()`. That's a cors requirement. – reggaemahn Jul 01 '19 at 12:43
  • @reggaemahn I meant to strip it to basics, to make sure the communication between client and server works. If that works you start modifying it (making it secure) step by step. – theCuriousOne Jul 02 '19 at 07:33
  • We recommend you test your app using the latest version (CompatibilityVersion.Version_2_2). We anticipate that most apps won't have breaking behavior changes using the latest version. From https://learn.microsoft.com/en-us/aspnet/core/mvc/compatibility-version?view=aspnetcore-2.2 – smoore4 Jul 03 '19 at 14:17

2 Answers2

0

The only thing CORS does is let the browser use the response from a cross-origin request, it will not make cookies cross-domain (see the specification for more details on the conditions for attaching a cookie to a request, it does not mention CORS at all).

If cookies could be sent along cross-origin request, that would be a major security flaw, since it would allow foreign domains to get sensitive information like user session tokens from your own domain. An evil developer could create an API providing a useful service, and then retrieve tons of session tokens from websites using the API (originating websites could be easily found through the Referer header).

The behavior you observed with localhost and different ports is normal since ports are not taken in account for cookies, which is "for historical reasons" (for reference: Are HTTP cookies port specific?)

So the options left for you are:

  • Set the cookie domain to a parent domain
  • Considering your server can work with headers instead of cookies, do not use cookies at all (use localStorage with javascript, and HTTP headers, for example)
  • Considering you have hands on the infrastructure, use a single domain for both UI and API, and do some URL rewriting on server side (e.g: incoming requests starting with /api/... are rewritten with the local API URL, others are rewritten with the local UI URL)
Community
  • 1
  • 1
Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • _The only thing CORS does is let the browser use the response from a cross-origin request._ Do you have a good source for this? – reggaemahn Jun 28 '19 at 23:27
  • I added the spec in my answer – Guerric P Jun 29 '19 at 00:40
  • I also disagree with "The only thing CORS does is let the browser use the response for a cross-origin request." CORS is a spec governing access to a REST service from a different domain. I've attached a link to the W3C spec for CORS. https://www.w3.org/TR/cors/#user-credentials You will also see specific verbiage regarding how cookies are handled – Paul Story Jul 01 '19 at 23:18
  • When sending cookies to a foreign domain, only the cookies set for that domain will be sent, not those from the current domain. You **cannot** share cookies between domains except if they trust each other and communicate via a dedicated channel, which is kinda hacky: https://stackoverflow.com/questions/3342140/cross-domain-cookies – Guerric P Jul 02 '19 at 16:54
  • @Twistingnether I am just hoping for some authoritative source on this. It's been a nightmare trying to understand this. The SO question you link to has people saying you can share cookies and other's saying you can't (both with a lot of upvotes). Additionally, cookies have a origin policy of _SameSite_, _LAX_ or _None_. This would clearly imply that sending them to a different domain should be possible. – reggaemahn Jul 04 '19 at 22:46
  • The only thing I can tell is that you won't find any standard way to share a cookie between domains, because doing so is an anti-pattern. You are citing the `SameSite` attribute, but it doesn't allow to share a cookie, it adds some protection against CSRF attacks by not adding the cookie when the page has been reached from outside the website (e.g: mail), which is not related at all – Guerric P Jul 05 '19 at 11:31
-2

Browser not sending cookies cross-origin cross domain with CORS enabled.

Every cook has domain associated with it so you can use *.abc.com and use it on abc.com and all subdomains of abc.com So make sure your cookies are *.abc.com options.Cookie.Domain = ".contoso.com";

see my link sharecookies like this

services.AddCors(options =>
        {
            options.AddPolicy(MyAllowSpecificOrigins,
            builder =>
            {
                builder.WithOrigins("http://example.com","*.example.com"
                                    "http://www.contoso.com");
            });
        });
Jin Thakur
  • 2,711
  • 18
  • 15