I'm having trouble getting Angular, CORS, SpringSecurity and Basic Authentication to play nicely. I have the following Angular Ajax call where I'm trying to set the header to include a Basic Authorization header in the request.
var headerObj = {headers: {'Authorization': 'Basic am9lOnNlY3JldA=='}};
return $http.get('http://localhost:8080/mysite/login', headerObj).then(function (response) {
return response.data;
});
I am running my angular app on localhost:8888 and my backend server on localhost:8080. So I had to add a CORS filter to my server side which is Spring MVC. So I created a filter and added it to my web.xml.
web.xml
<filter>
<filter-name>corsFilter</filter-name>
<filter-class>com.abcinsights.controller.SimpleCorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
CorsFilter
public class SimpleCorsFilter extends OncePerRequestFilter {
@Override
public void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
Enumeration<String> headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
System.out.println("headerName " + headerName);
System.out.println("headerVal " + req.getHeader(headerName));
}
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type, Authorization");
chain.doFilter(req, res);
}
}
This all works fine and when I look at the header names/values I see my Authorization header with the Basic value and the hard coded Base64 string.
So then I tried to add SpringSecurity which would use the Authorization header to do basic authentication. Here's my web.xml and spring security config with Spring Security added in.
updated web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/security-config.xml</param-value>
</context-param>
<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>
security-config.xml
<http auto-config="true" use-expressions="false">
<intercept-url pattern="/**" access="ROLE_USER" />
<http-basic/>
<custom-filter ref="corsHandler" before="SECURITY_CONTEXT_FILTER"/>
</http>
<beans:bean id="corsHandler" class="com.abcinsights.controller.SimpleCorsFilter"/>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
</authentication-manager>
As you can see, I had to add my CORS filter to the front of the spring security filter chain (I also removed it from web.xml). This seems to be working in the sense that the CORS filter still gets called when I make a request. But the request coming from my AJAX call no longer has the Authorization header added in. When I remove the SpringSecurity filter chain and just put my CORS filter back into web.xml the Authorization header comes back. I'm at a loss but am wondering if it has something to do with preflight communication working one way when my CORS filter is stand alone in web.xml and another way when it is in the Spring Security filter chain? Any help would be appreciated.
Thanks