In my Spring Boot/AngularJS application I have the following CSRF- Configuration:
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(csrfTokenRepository()); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
final String[] restEndpointsToSecure = WebSecurityConfig.restEndpointsToSecure;
for (final String endpoint : restEndpointsToSecure) {
http.authorizeRequests().antMatchers("/" + endpoint + "/**").hasRole(UserRoleEnum.USER.toString());
}
http.addFilterAfter(csrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
xAuthTokenConfigurer.setDetailsService(userDetailsServiceBean());
final SecurityConfigurer<DefaultSecurityFilterChain, HttpSecurity> securityConfigurerAdapter = xAuthTokenConfigurer;
http.apply(securityConfigurerAdapter);
}
The CSRF- Token Filter looks like this:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, javax.servlet.FilterChain filterChain)
throws ServletException, IOException {
final CsrfToken csrf = (CsrfToken)request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
final String token = csrf.getToken();
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
In general it works fine, the Request header property X-XSRF-TOKEN is send with each request. BUT I have a strange behaviour. I will update my user- profile in application. The first time it works fine, the second one, I get an HTTP 403 Forbidden and actually I really don't know why. I do nothing between this two updates (no navigation to other pages between this two updates or something else).
At the picture at the bottom the left Request is the one which works and the right one failes. The only different is that at the right one the property Set-Cookie and X-Application-context is missing in Response header. The request headers are equal.
Does anyone know what I am doing wrong here. Its kind of mystic here for me.
It seems as though there might be some functional error
in your front-end
userProfile.controller
Your Cookie SessionID redirected form the request header is getting same in the response header which results in INVALID_SESSIONID hence the user is redirected to the login page or your signup page
As a Solution to this you can either correct your frontend controller or as another workaround for this you can add the following to your code
Respond to the OPTIONS request with a http 200 message
static final String ORIGIN = "Origin";
if (request.getHeader(ORIGIN).equals("null")) {
String origin = request.getHeader(ORIGIN);
response.setHeader("Access-Control-Allow-Origin", "*");//* or origin as u prefer
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers",
request.getHeader("Access-Control-Request-Headers"));
}
if (request.getMethod().equals("OPTIONS")) {
try {
response.getWriter().print("OK");
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
Then add the custom filter to be invoked
//your other configs
< security:custom-filter ref="corsHandler" after="PRE_AUTH_FILTER"/>