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 theOPTIONSrequest to succeed. Because if you send back a different non-wildcard origin value than what theOPTIONSsucceeded 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
Originheader to the request. AndAccess-Control-Allow-Originis only used by browsers.So there’s no point in sending back
Access-Control-Allow-Originto non-browser tools that haven’t sent anOriginin the request—in that case, it’s just wasted bytes you’re sending out.Of course somebody can use
curlor whatever non-browser tool to send a request to the server, and manually add anOriginheader 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-Originresponse header at all for those cases. That’s the semantics of the header being missing: If the server sends noAccess-Control-Allow-Originresponse 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-Originresponse 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
Originheader with the valuenulland unless you intentionally want to allow all requests withOrigin: nullto 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
nullpart of the answer at When does Firefox set the Origin header to null in POST requests?