1

When I deploy my app on the server, first time I can log in without problems. But when I log out I get "403 Forbidden" on the logout post request. Then I cannot log in successfully because I get the 403 error on the login request. Ctrl+F5, trying to log in again and... it works, but only one time.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
http
                .authorizeRequests()
                .antMatchers("/apps", "/sites", "/users").authenticated()
                .and()
                .csrf()
                .csrfTokenRepository(csrfTokenRepository())
                .and()
                .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setHeaderName("X-XSRF-TOKEN");
    return repository;
}

and the CsrfHeaderFilter class:

public class CsrfHeaderFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class
                .getName());
        response.setHeader("X-CSRF-HEADER", token.getHeaderName());

        response.setHeader("X-CSRF-PARAM", token.getParameterName());

        response.setHeader("X-XSRF-TOKEN", token.getToken());

        if (token != null) {
            Cookie cookie = WebUtils.getCookie(request, "X-XSRF-TOKEN");
            if (cookie == null || token != null && !token.equals(cookie.getValue())) {
                cookie = new Cookie("X-XSRF-TOKEN", token.getToken());
                cookie.setPath("/");
                response.addCookie(cookie);
            }
        }
        filterChain.doFilter(request, response);
    }

and in Angular:

$httpProvider.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';

My app is deployed at localhost:8080/myApp if it matters.

ahoj pepiczki
  • 309
  • 1
  • 3
  • 18
  • How do you do the logout? – Doron Sinai Aug 11 '15 at 16:46
  • @DoronSinai in angular I send a post request and then do this: `this.id = null;data = {}; delete $cookies.session;` and, what's funny, I can't find controller which handles /logout request in Spring. That's strange. – ahoj pepiczki Aug 11 '15 at 17:01
  • @DoronSinai, my mistake. There's a handler for logout request: `private static final String CURRENT_USER_ATTRIBUTE = "currentUser"; @Override public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { httpServletRequest.getSession().removeAttribute(CURRENT_USER_ATTRIBUTE); httpServletResponse.setStatus(HttpServletResponse.SC_OK); httpServletResponse.getWriter().flush(); }` – ahoj pepiczki Aug 11 '15 at 17:03
  • Why are you deleting $cookies.session;? Also can you see if the logout post have the XSRF token – Doron Sinai Aug 11 '15 at 17:18

1 Answers1

2

After certain events like login, logout, the CSRF token changes. So, the next POST request would fail, as in your case. I faced the same issue, and after some diagnosis, found that sending another GET request following login, logout etc. would be the best way to tackle it. (If you are not using CORS, you may as well have the login, logout send a redirect response). See this stackoverflow post for more details.

Community
  • 1
  • 1
Sanjay
  • 8,755
  • 7
  • 46
  • 62
  • I'm shocked, it works. Do you have any explanation why? – ahoj pepiczki Aug 12 '15 at 09:06
  • Because the SESSION invalidates by default, the CSRF token, which is stored in the session by default, changes. See the comments in this post: http://stackoverflow.com/questions/31654565/spring-single-page-application-csrf-token-changing-silently-after-login-logout – Sanjay Aug 12 '15 at 10:38