Recently I start implementing a token based security system with angularjs and spring mvc. The idea is the following: 1. Visit /user/authenticate to get a security token and save the token to local storage 2. For each request sent by the angularJS client, use an interceptor to inject a X-Auth-Token header to the request.
In my spring back-end I have implemented an AuthenticationTokenProcessingFilter and a CustomAuthenticationEntryPoint. The first for extracting the token from the header and check if it is valid and the second to return a 401 unauthorized status when a request is not authenticated.
Please find some details about my back end code
AuthenticationController.java
@RestController
@RequestMapping(value="user")
public class AuthenticationController {
@RequestMapping(value="authenticate", method = RequestMethod.POST)
public ResponseEntity<?> login(@RequestParam("email") String email,
@RequestParam("password") String password) {
//Check if user is valid and return token
}
}
SecurityConfig.java
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UsersRepository usersRepo;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {...}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(
new AuthenticationTokenProcessingFilter(usersRepo),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(this.corsFilter(), UsernamePasswordAuthenticationFilter.class)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable().exceptionHandling()
.and()
.httpBasic()
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/user/authenticate").permitAll()
.antMatchers("/**").authenticated()
.anyRequest().authenticated();
}
@Bean
public CORSFilter corsFilter() {
return new CORSFilter();
}
}
CORSFilter.java
public class CORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, Origin, X-Auth-Token");
response.addHeader("Access-Control-Expose-Headers", "X-Auth-Token");
chain.doFilter(req, res);
}
}
Now I am using the following angularjs code in order to query the /user/authenticate endpoint which is not behind firewall
return $http.post(baseUrl + 'user/authenticate', 'email='+username+'&password='+password,
{
headers : {
'content-type' : 'application/x-www-form-urlencoded'
}
}
);
When I use the above code everything works. However If I remove the headers parameter from the request my angularjs client sends an OPTION request (rather than a POST request - I imagine this is related to my CORS filter) and my back end sends a 401 Unauthorised response.
Could you please give me a few more details why this is happening?
Thank you in advance!