Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cross origin request with CORS filter

I'm trying to make cross origin requests from an AngularJS 1.3 app to a REST service. Although I enabled CORS Filter, I get a 403 Forbidden response. Here's the request (copy paste from chrome dev tools). On IE 9 it appears to work. I get 403 error code on Chrome and Firefox.

Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/<path>
Request Method:OPTIONS
Status Code:403 Forbidden
Request Headersview source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en,ro;q=0.8,en-US;q=0.6,en-GB;q=0.4
Access-Control-Request-Headers:x-auth-token, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, ike Gecko) Chrome/40.0.2214.111 Safari/537.36
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Origin, Accept, x-auth-token, Content-Type,        
Access-Control-Request-Method, Access-Control-Request-Headers
Access-Control-Allow-Methods:POST, GET, HEAD, OPTIONS
Access-Control-Allow-Origin:http://localhost:9000
Content-Length:0
Content-Type:text/plain
Date:Tue, 17 Feb 2015 07:11:24 GMT
Server:Apache-Coyote/1.1

The URL is ok. If I paste it into the browser directly it works.

The cross origin authentication works:

Remote Address:127.0.0.1:8080
Request        
URL:http://localhost:8080/<serviceName>/webapi/authentication/authenticate
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en,ro;q=0.8,en-US;q=0.6,en-GB;q=0.4
Connection:keep-alive
Content-Length:42
Content-Type:application/json;charset=UTF-8
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,     like Gecko) Chrome/40.0.2214.111 Safari/537.36
Request Payload
{username: "user", password: "pass"}
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:9000
Content-Length:100
Content-Type:application/json
Date:Tue, 17 Feb 2015 07:11:24 GMT
Server:Apache-Coyote/1.1
Set-Cookie:JSESSIONID=805B2490C0BA258D7D0FF4235BA49B76; Path=/<appcontext>/;     
HttpOnly

I'm using Spring Security for authentication. What else do I need for cross origin requests?

CORS filter used:

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class CORSFilter2 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse     servletResponse, FilterChain filterChain) throws IOException, ServletException {
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:9000");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, x-auth-token, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }

}

like image 281
Mihai Serban Avatar asked Feb 10 '23 21:02

Mihai Serban


2 Answers

By CORS non-GET requests send preflight request in browser automatically. You should allow OPTIONS method on your HTTP server and in the CORS allow headers to serve these requests. Your server should respond with CORS allow headers and 200 ok with empty response body to the preflights.

According to your comments the problem is probably caused by your custom x-auth-token header, which is not sent by the OPTIONS request, so your server responded with 403 forbidden.

A preflight call is a call to determine if an action is allowed. It should not require credentials to determine if I can do something, it should only require credentials to actually do it.

  • CORS preflight issues in Firefox and Chrome

I agree with Ryan, you should not check auth headers by OPTIONS.

like image 99
inf3rno Avatar answered Feb 20 '23 03:02

inf3rno


In the case of preflighted CORS requests, you need to be aware that credentials aren't sent in the OPTIONS request. If the latter sends back the correct CORS headers in its response, the target request is then called with the credentials. That's why you have the 403 status code...

So you need to tweak your CORS filter not to try to authenticate this OPTIONS request.

In addition to the previous answer, this link could help you to solve your problem: https://templth.wordpress.com/2014/11/12/understanding-and-using-cors/.

like image 22
Thierry Templier Avatar answered Feb 20 '23 01:02

Thierry Templier