Cross origin request with CORS filter
ajax, angularjs, cors, cross-domain, rest
Solution
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.
Problem
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() { } ``` }