celineu
celineu

Reputation: 586

Spring Security + AngularJS: POST request

I have a web application with the back using Java Spring and the front using AngularJS.

Spring Security Configuration (Java config):

@Override
protected void configure(HttpSecurity http) throws Exception {
        http
        .authenticationProvider(authenticationProvider())
        .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
        .and()
        .formLogin().loginProcessingUrl("loginProcessingUrl")
                    .successHandler(authSuccessHandler)
                    .failureHandler(authFailureHandler)
                    .usernameParameter("username")
                    .passwordParameter("password")
        .and()
        .logout().permitAll().logoutSuccessHandler(logoutSuccessHandler)
        .and()
        .authorizeRequests().antMatchers("/demo/**","/postTest/**").permitAll()
        .anyRequest().authenticated()
        .and()
        .httpBasic()
        .and()
        .csrf().csrfTokenRepository(csrfTokenRepository())
        .and()
        .addFilterAfter(new CsrfCustomFilter(), CsrfFilter.class);
    }

CSRF filter:

public class CsrfCustomFilter extends OncePerRequestFilter{

@Override
protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
    if (csrf != null) {
      Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
      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);
}
}

POST request from AngularJS:

$http({method:'POST',data:"celine",url:"http://localhost:8080/postTest",cache:true})
        .success(function(data) {
          console.log("success POST");
        })
        .error(function(data, status, headers, config, statusText) {
          console.log("status: " + status + " statusText: " + statusText);
        });

-- UPDATED --
I can use a GET request from the front to the back, but the POST request doesn't seem to work. I get a 403 Forbidden error on the front side (in my log: "status: 403 statusText: undefined").

For the POST request, I can correctly send a XSRF-TOKEN to Spring, but Spring returns 403 Forbidden. So I guess that the problem is coming from my configuration of Spring Security and not from Angular.

My headers for the POST request: enter image description here

Thank you for your time.

Upvotes: 1

Views: 2682

Answers (1)

Sanjay
Sanjay

Reputation: 8965

I had a similar problem with cross domain requests, because AngularJS does not send the XSRF header in cross domain requests. (Search for "The header will not be set for cross-domain requests" on this page).

Writing this $http interceptor

angular.module('appBoot')
  .factory('XSRFInterceptor', function ($cookies, $log) {

    var XSRFInterceptor = {

      request: function(config) {

        var token = $cookies.get('XSRF-TOKEN');

        if (token) {
          config.headers['X-XSRF-TOKEN'] = token;
          $log.info("X-XSRF-TOKEN: " + token);
        }

        return config;
      }
    };
    return XSRFInterceptor;
  });

and configuring it like this

angular.module('appBoot', ['ngCookies', 'ngMessages', 'ui.bootstrap', 'vcRecaptcha'])
    .config(['$httpProvider', function ($httpProvider) {

      $httpProvider.defaults.withCredentials = true;
      $httpProvider.interceptors.push('XSRFInterceptor');

    }]);

solved my problem.

Upvotes: 1

Related Questions