httpcorshttp-accept-header

Is Access-Control-Allow-Origin required for the preflight AND the actual request?


I am implementing a router to process all web requests.

OPTIONS requests come in and I am responding with:

header('Access-Control-Allow-Origin: http://localhost:4000');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
header('Access-Control-Allow-Headers: authorization');
header('Access-Control-Allow-Credentials: true');
header('Vary: Origin');

And also I am sending all those for the GET/POST/PUT/DELETE requests.

Is sending those headers for those "real" requests unnecessary?


Solution

  • The Fetch standard is the (somewhat dry) source of truth for the CORS protocol; you can find answers to all your questions about CORS in there; see, in particular,

    Some CORS response headers are only used in preflight responses:

    Other CORS response headers are used in both the preflight response and the actual response:

    Is sending those headers for those "real" requests unnecessary?

    Note that, if one or both of those headers (Access-Control-Allow-Origin and Access-Control-Allow-Credentials) are actually needed in the preflight response, they're also needed in the actual response.

    Finally, one CORS response header is only used in the actual response: Access-Control-Expose-Headers.

    The case of the Vary header is interesting. Since, in theory, responses to OPTIONS requests are not cacheable (outside of browsers' preflight cache), the Vary header should have no place in such responses. However, some caching intermediaries do allow their users to cache responses to OPTIONS requests, and omitting the Vary header from those responses may lead to Web cache poisoning.

    This difficulty is a good indication that you shouldn't be implementing CORS by manually setting response headers. Instead, rely on a good CORS middleware library that can abstract all this complexity for you.