No 'Access-Control-Allow-Origin' header is present on the requested resource + The response had HTTP status code 401

Lyle Rolleman picture Lyle Rolleman · May 16, 2017 · Viewed 47.6k times · Source

XMLHttpRequest cannot load http://192.168.1.253:8080/... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 401.

Pretty common error, with a great many possible solutions that haven't worked. I understand (I think) how CORS is supposed to work, and I don't see anything wrong with my HTTP headers, but it still doesn't work

From Chrome:

Request URL:http://192.168.1.253:8080/...
Request Method:OPTIONS
Status Code:200 OK
Remote Address:192.168.1.253:8080
Referrer Policy:no-referrer-when-downgrade
Response Headers
Access-Control-Allow-Headers:x-requested-with,accept,content-
type,authorization
Access-Control-Allow-Methods:POST, GET, PUT, PATCH, OPTIONS, DELETE
Access-Control-Allow-Origin:*
Access-Control-Max-Age:3600
Allow:GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Connection:keep-alive
Content-Length:0
Date:Mon, 15 May 2017 21:50:55 GMT
Expires:0
Pragma:no-cache
Server:...
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:authorization,content-type
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:192.168.1.253:8080
Origin:http://localhost:4200
Pragma:no-cache
Referer:http://localhost:4200/...
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36

My understanding is the OPTIONS response needs the Access-Control-Allow-Origin header set and allow the method type and header values, which it does

Relevant angular below. I've done a fair number of different combinations of this with all sorts of different stuff in the header, but nothing works

private getObject<T>(path: string): Promise<T> {
    return this.http.get(SERVER_URL + path, this.authenticationToken())
        .toPromise()
        .then(response => response.json() as T)
        .catch(this.handleError);
}

private authenticationToken() : RequestOptions {
    let login = JSON.parse(sessionStorage.getItem('currentLogin'));
    if (login && login.authenticationToken) {
        let headers = new Headers({ 
            'Authorization': 'Basic ' + login.authenticationToken,
            'Content-type': 'application/json', 
          });
        return new RequestOptions({ headers: headers });
    }
}

I got the feeling I'm missing something obvious but it's driving me nuts, any help is appreciated. Note this does work with a pre-existing Ember application so I don't think it's the server

Answer

sideshowbarker picture sideshowbarker · May 16, 2017

The response had HTTP status code 401.

401 indicates an authentication error. The error message in the question isn’t for a response from a preflight OPTIONS request. It instead seems to be for the actual GET request you’re trying to send.

So based on that error message, it seems the most likely scenario is that the browser’s preflight OPTIONS request succeeded but your GET request is not succeeding due to authentication failure.

So the server’s returning a 401 response/error page. And many/most web servers aren’t configured to send the Access-Control-Allow-Origin response header for error responses/pages. That’s the only reason you’re also getting a message about that header being missing.

But that missing header for the error response is not the cause of your problem; instead, the 401 is.

So it seems you probably want to figure out what’s causing the server to send a 401 response—why you’re getting an authentication failure. If you fix that it seems likely you’ll get a response from the server that includes the Access-Control-Allow-Origin response header as expected.