Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS with Authorization fails (NS_ERROR_DOM_BAD_URI)

Sorry for posting this rather large post. But I don't see a way to get it any smaller. Blame CORS :)

Versions:

  • Angularjs Version: 1.1.3
  • Jetty Version: 8.1.9
  • Jetty Servlets Version: 8.1.9.v20130131 (Used for Jettys CrossOriginFilter)

What I want to achieve

Cross Origin Request using Basic Authorization header:

  • with $http method from Angularjs originating from localhost:8000
  • to localhost:8080/api/user (Spring MVC REST interface).

Issue:

  • HTTPFox shows that OPTIONS request to /api/user was denied with Response 302 (NS_ERROR_DOM_BAD_URI)
  • Server is responding with 302 instead of 200 if Authorization Basic header is sent.
  • So called Simple CORS headers work (without Angularjs Authorization Basic header set).
  • Angularjs returns 0 as status (instead of 302 or 200).
  • In the Response Header of HTTPFox Location header redirects as if Authorization failed
  • Tests with Curl (with Authorization Header set) work without any issues
  • Supplied Base64 encoded Authorization String is correct.

Questions:

  • What is the reason for OPTIONS 302 (NS_ERROR_DOM_BAD_URI)? How can I solve it?
  • Why does Angularjs return 0 instead of 302 or 200 (seems an issue with x-requested-with)?
  • Is using Cross Origin with browsers really a good idea for production (it seems like there are many issues)?

CORS settings in web.xml of Spring configuration:

allowedOrigins: *
allowedMethods: GET,POST,DELETE,PUT,HEAD,OPTIONS
allowedHeaders: origin,content-type,accept,authorization,x-requested-with
supportsCredentials: true

Angularjs http request (Origins from: localhost:8000):

$http.get('localhost:8080/api/user', {headers: {'Authorization':'Basic am9obkBqb2huLmNvbTpibGE='}})
  .success(function(data, status, head, config) {
    console.log("success");
    console.log(status);
  })
  .error(function(data, status, head, config) {
    console.log("error");
    console.log(status);
  });

HTTPFox Request Headers (from OPTIONS request that fails):

(Request-Line)  OPTIONS /api/user HTTP/1.1
Host    localhost:8080
User-Agent  Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-US,en;q=0.5
Accept-Encoding gzip, deflate DNT   1
Origin  localhost:8000
Access-Control-Request-Method   GET
Access-Control-Request-Headers  authorization
Connection  keep-alive

HTTPFox Response Headers (from OPTIONS request that fails):

(Status-Line)   HTTP/1.1 302 Found
Access-Control-Allow-Origin localhost:8000
Access-Control-Allow-Credentials    true
Access-Control-Max-Age  1800
Access-Control-Allow-Methods    GET,POST,DELETE,PUT,HEAD,OPTIONS
Access-Control-Allow-Headers    origin, content-type, accept, authorization, x-requested-with
Location    localhost:8080/login.jsp
Content-Length  0
Server  Jetty(8.1.9.v20130131)

Spring DEBUG Log:

[qtp1172726060-24 - /api/user] DEBUG org.eclipse.jetty.server.Server - REQUEST /api/user on AsyncHttpConnection@c114739,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-5,l=10,c=0},r=1
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlet.ServletHandler - chain=CORS->springSecurityFilterChain->spring
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlet.ServletHandler - call filter CORS
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlets.CrossOriginFilter - Cross-origin request to /api/user is a preflight cross-origin request
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlets.CrossOriginFilter - Access-Control-Request-Method is GET
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlets.CrossOriginFilter - Method GET is among allowed methods [GET, POST, DELETE, PUT, HEAD, OPTIONS]
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlets.CrossOriginFilter - Access-Control-Request-Headers is authorization
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlets.CrossOriginFilter - Headers [authorization] are among allowed headers [origin,  content-type,  accept,  authorization,  x-requested-with]
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlets.CrossOriginFilter - Preflight cross-origin request to /api/user forwarded to application
[qtp1172726060-24 - /api/user] DEBUG o.e.jetty.servlet.ServletHandler - call filter springSecurityFilterChain
[qtp1172726060-24 - /api/user] DEBUG org.eclipse.jetty.server.Server - RESPONSE /api/user  302 handled=true
[qtp1172726060-24] DEBUG o.e.jetty.server.AsyncHttpConnection - Enabled read interest SCEP@5deb702b{l(/127.0.0.1:41667)<->r(/127.0.0.1:8080),d=true,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=0r}-{AsyncHttpConnection@c114739,g=HttpGenerator{s=4,h=0,b=-1,c=-1},p=HttpParser{s=0,l=10,c=0},r=1}

Web.xml:

<!-- CORS related filter (this comes before the security filter -->
<filter>
    <filter-name>CORS</filter-name>
    <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>

    <init-param>
        <param-name>allowedOrigins</param-name>
        <param-value>*</param-value>
    </init-param>
    <init-param>
        <param-name>allowedMethods</param-name>
        <param-value>GET,POST,DELETE,PUT,HEAD,OPTIONS</param-value>
    </init-param>
    <init-param>
        <param-name>allowedHeaders</param-name>
        <param-value>origin, content-type, accept, authorization, x-requested-with</param-value>
    </init-param>
    <init-param>
        <param-name>supportsCredentials</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>CORS</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Security related filter -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
like image 558
Christopher Armstrong Avatar asked Apr 28 '13 11:04

Christopher Armstrong


People also ask

What does Ns_error_dom_bad_uri mean?

This means that either the port, domain, or protocol is not the same between the URI that you are sending a request TO and the URL that you are sending the request FROM. You can overcome this by adding headers to your server side code: Access-Control-Request-Headers.

How do I get rid of CORS policy error?

Short description. Cross-Origin Resource Sharing (CORS) errors occur when a server doesn't return the HTTP headers required by the CORS standard. To resolve a CORS error from an API Gateway REST API or HTTP API, you must reconfigure the API to meet the CORS standard.

How do I fix CORS error in HTML?

to fix the error, you need to enable CORS on the server. The client expects to see CORS headers sent back in order to allow the request. It might even send a preflight request to make sure that the headers are there. You can enable CORS server side for one, multiple, or all domains hitting your server.

What is CORS and how do you fix it?

CORS is an abbreviation for Cross-Origin Response Sharing. It is what allows the website on one URL to request data from a different URL, and it frustrates both the frontend and backend devs alike. You might've added an image URL only to end up with something like this.


1 Answers

We use CORS in production but it will only work on HTML5 complaint browsers, and we had the same problems.

The only difference between our client-side and yours is that you are not passing the withCredentials to the get method.

Like this:

$http.get(url, { withCredentials : true })

You can also set as default:

config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.withCredentials = true;
}]);

If neither of this work, try changing your CORS servlet to this.

like image 113
pedroassis Avatar answered Sep 23 '22 08:09

pedroassis