269

I'm trying to understand how to use CORS and am confused about what the Access-Control-Allow-Credentials header does.

The documentation says

Indicates whether or not the response to the request can be exposed when the credentials flag is true.

But I don't understand what the response being "exposed" means.

Can anyone explain what this header being set to true (in conjunction with the credentials flag being set to true) actually does?

Abdull
  • 26,371
  • 26
  • 130
  • 172
Nate
  • 26,164
  • 34
  • 130
  • 214
  • xhr.withCredential doc on client side https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials – Weishi Z May 27 '16 at 21:04
  • That doesn't talk about headers, but about xhr. If you use anything else, like Blazor WebAssembly, you gain nothing from that description. I still don't know if Access-Control-Allow-Credentials is identical to credentials: include or how to set it in Blazor wasm. – Jens Mander Jul 20 '21 at 19:32

1 Answers1

405

By default, CORS does not include cookies on cross-origin requests. This is different from other cross-origin techniques such as JSON-P. JSON-P always includes cookies with the request, and this behavior can lead to a class of vulnerabilities called cross-site request forgery, or CSRF.

In order to reduce the chance of CSRF vulnerabilities in CORS, CORS requires both the server and the client to acknowledge that it is ok to include cookies on requests. Doing this makes cookies an active decision, rather than something that happens passively without any control.

The client code must set the withCredentials property on the XMLHttpRequest to true in order to give permission.

However, this header alone is not enough. The server must respond with the Access-Control-Allow-Credentials header. Responding with this header to true means that the server allows cookies (or other user credentials) to be included on cross-origin requests.

You also need to make sure your browser isn't blocking third-party cookies if you want cross-origin credentialed requests to work.

Note that regardless of whether you are making same-origin or cross-origin requests, you need to protect your site from CSRF (especially if your request includes cookies).

John
  • 1
  • 13
  • 98
  • 177
monsur
  • 45,581
  • 16
  • 101
  • 95
  • So the settings have to do with cookies being sent with the request, not with cookies being returned in the response? I was under the impression cookies were always sent with requests (even JSONP). – Nate Jul 11 '14 at 09:03
  • 1
    I clarified the answer to cover your question. Basically JSON-P does it wrong, and is less secure. – monsur Jul 11 '14 at 13:25
  • 49
    Just want to add to this a little bit to comment on the meaning of "exposed." The spec doesn't require a pre-flight (additional roundtrip to check if the server will allow credentials) for GET requests. Instead of preflighting, the browser will just always make the request, sending cookies if `withCredentials` is set, but then when it receives the response, if withCredentials was set, it will only deliver/expose the result to the calling javascript if the response has the Access-Control-Allow-Credentials header set. If no header, it doesn't expose the response, effectively black-holing it. – heavi5ide May 13 '15 at 20:25
  • 4
    @heavi5ide, Yea, even if the browser doesn't expose the response to the client code, the request-with-cookie was still sent (for non-preflighted requests). So CSRF would still be done. – Pacerier Jan 26 '16 at 06:36
  • @monsur, Actually it's not so much that "*the server allows cookies (or other user credentials) to be included on cross-origin requests*". It's not a matter of allowance.. rather, the header is what the server uses to signify to the browser that it's OK to send them because it is expecting so. – Pacerier Jan 26 '16 at 06:36
  • 9
    Since this is such a popular answer, I'm going to add one more important piece of information: in addition to configuring your request and response headers correctly, you also need to make sure your browser isn't blocking third-party cookies if you want cross-origin credentialed requests to work. See http://stackoverflow.com/a/16634887/2970321 – alexw Feb 18 '16 at 15:49
  • A small addition to @heavi5ide's and @Pacerier's comments. Other than GET, there are also POST requests (and more) that will not trigger a preflight, and this needs to be remembered since many CSRF attacks consist of a POST request, which would be successful in this scenario even if `Access-Control-Allow-Credentials` was not set. Details of which requests trigger preflights can be found at [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests) – AntonioHerraizS Jun 16 '16 at 19:04
  • 12
    This is such a clear answer that anyone reading it the first time can understand and fix their code that doesn't seem to be working well with cookies. Thanks! – asgs Jun 21 '16 at 18:06
  • @alexw: I've added that note to the answer for you. Feel free to delete the comment. – Dan Dascalescu Oct 22 '16 at 01:39
  • 1
    Finally! Someone who can explain CORS. See you also wrote a book... which is great, yet daunting - CORS is so complex we need an entire book on the subject – tim-montague Sep 30 '17 at 23:55
  • 1
    "Responding with this header to true means that the server allows cookies (or other user credentials)..." what "other user credentials"? Headers? – Ian Kemp Oct 17 '19 at 13:47
  • @monsur *"However, this header alone is not enough."* - what **header**? Maybe you meant that setting `withCredentials` **property** (this is not a **header**) is not enough? – Ruslan Stelmachenko Sep 20 '20 at 12:44
  • 3
    Applies this to Authorization headers? – alvaropgl Feb 11 '21 at 08:18
  • If the default setting for coookies is SameSite=Lax, then what is the point of Access-Control-Allow-Credentials? Say you attempt a CSRF POST request from a victim's browser, for the cookie to be included in the request, the web app developer would have had to have set SameSite=None explicitly, so why would they also not want the response to be visible to the Javascript? Seems as though Access-Control-Allow-Credentials is redundant and can always be left out. Or is there a situation where the designer of a web app would want cookie sent with cross origin requests, but have the response unavail – David Klempfner Jul 03 '21 at 00:45
  • If I understand correctly, setting withCredentials on xhr to true sends some header with the request. Which header is that? What are it's name and value? I am trying to find out how to set that header (of which I don't know the name or possible values) from Blazor Webassembly. – Jens Mander Jul 20 '21 at 19:38
  • @alvaropgl I think yes, when it is a Basic Auth cached into a browser. Again: not a Basic auth provided by javascript code that set a header. if a browser caches those credentials (Cookies, Basic Auth requested by WWW-Authenticate, and may be something that I didn't know) then those credentials are vulnerable by CSRF and in the same manner are restricted to pass automatically via the Browser. JavaScript code may pass any Authorization header that it wants: it is unrelated to CSRF. – Pavel Patrin Jul 23 '21 at 19:18
  • Does anyone know a situation where the existence of this header would save a buck for anyone? I try hard to find a logic in this, looks like: hey server, I am browser and I sent you my client's credentials, if you want me to use your response please confirm! **1.** Ok, hey browser, I am server, I did gave you an answer (by checking the credentials too), but you know what? I was probably drunk then, so I don't allow you to use it! or **2.** ...I respond with 403 but hey: credentials are true! ☺️☺️☺️ – Sorin GFS Apr 30 '22 at 08:15
  • So are localhost:3000 & localhost:4000 same-site or cross-site ? I understand they are cross-origin but what about site ? In MDN docs for withCredentials, it talks about same-site not origin. It does not without setting withCredentials to true on frontend. – Yusuf May 05 '22 at 16:52
  • We have a form that can be either used by guest users or authenticated users. If authenticated there is token available in Cookies... do we need to set `Access-Control-Allow-Credentials` to `true` in our CORS config or should it be false? Or should be based on whether user is guest or not? – xbmono Jun 04 '22 at 04:53
  • 1
    Since token-based APIs are morern these days - Correct me if I'm wrong, but it seems that if your API is using `Authorization: Bearer ...` authentication, then you don't need `Access-Control-Allow-Credentials`, but rather `Access-Control-Allow-Headers: authorization`. And if you don't need it, better not enable it to be on the safe side. – mh8020 Aug 11 '22 at 06:22
  • Some questions: What does "exposed" to JavaScript mean for an HttpOnly cookie? Is it possible somehow using XSS to hijack the (returned) cookie? Also - in which way adding this header makes CSRF _more_ possible than without it in the context of HttpOnly cookie? – krulik Sep 29 '22 at 20:29
  • 1
    This answer, and more specifically the following passage, is outdated/misleading: _In order to reduce the chance of CSRF vulnerabilities in CORS, CORS requires both the server and the client to acknowledge that it is ok to include cookies on requests._ Try opening your browser's Console tab on this page and run `fetch('//example.com', {include: 'credentials', mode: 'no-cors'})`. Your browser will issue a cross-origin credentialed request, without the need for `https://example.com` being configured for CORS. – jub0bs May 08 '23 at 16:46