I have a general idea about how it works. I return the same "ORIGIN" value if the the request's "origin" header is valid (allowed)
But I don't know:
- For the actual request following the OPTIONS request, do I need to include the exact same Access-Control-Allow-Origin header that I returned to the client for the preflight request? Should the server code only need to do this when there is an "ORIGIN" header present in the actual request? (in the code below, I did not check whether the request is a OPTIONS/preflight request or the actual one, I assume the same code can apply to both with no harm).
(More details, because "The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'," so I need the ORIGIN value from the request to put back into the response.
What should I return if the ORIGIN is not allowed?
not including the Access-Control-Allow-Origin header at all?
or setHeader("Access-Control-Allow-Origin", ""), or setHeader("Access-Control-Allow-Origin", "null")?
public class CORSResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
String origin = requestContext.getHeaderString("Origin");
String origin = requestContext.getHeaderString("Origin");
URL originUrl = null;
try {
if (StringUtils.hasText(origin)) {
originUrl = new URL(origin);
Pattern hostAllowedPattern = Pattern.compile("(.+\\.)*mydomain\\.com", Pattern.CASE_INSENSITIVE);
if (hostAllowedPattern.matcher(originUrl.getHost()).matches()) {
headers.add("Access-Control-Allow-Origin", origin);
} else {
headers.add("Access-Control-Allow-Origin", "");
}
headers.add("Vary", "Origin");
}
headers.add("Access-Control-Allow-Credentials", "true");
headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
headers.add("Access-Control-Allow-Headers",
Yes—that is, if you’re sending back an actual origin value and not the "
*
" wildcard, and that origin value is what caused theOPTIONS
request to succeed. Because if you send back a different non-wildcard origin value than what theOPTIONS
succeeded with, that’ll cause the browser to block the client code from accessing the response (because the actual origin won’t match).Yes, because when frontend JavaScript code running in a browser uses XHR or the Fetch API or an Ajax method from some JavaScript library to make a cross-origin request, browsers always add an
Origin
header to the request. AndAccess-Control-Allow-Origin
is only used by browsers.So there’s no point in sending back
Access-Control-Allow-Origin
to non-browser tools that haven’t sent anOrigin
in the request—in that case, it’s just wasted bytes you’re sending out.Of course somebody can use
curl
or whatever non-browser tool to send a request to the server, and manually add anOrigin
header to the request. But that’s OK—in that case, the response they’ll get is the same response you’d send to a browser. So that can actually be helpful for testing.Yes. Just don’t send back the
Access-Control-Allow-Origin
response header at all for those cases. That’s the semantics of the header being missing: If the server sends noAccess-Control-Allow-Origin
response header, that means the server isn’t opting in to allowing cross-origin requests from frontend code running browsers, so the default same-origin policy applies.That is, by not sending the
Access-Control-Allow-Origin
response header, the server’s telling browsers: “Please use the default same-origin policy as usual and prohibit access to this response from all frontend JavaScript code at the origin that sent this request.”No, there’s never any need to send back an empty value like that. It doesn’t mean anything special.
Definitely don’t do that. There are many cases where a browser will send an
Origin
header with the valuenull
and unless you intentionally want to allow all requests withOrigin: null
to access responses from the server, don’t do that.For details, see the When browsers must internally set origin to a value that’ll get serialized as
null
part of the answer at When does Firefox set the Origin header to null in POST requests?