title: Spring SAML Extension and Spring Security CSRF Protection Conflict
body: <p>We have a Spring MVC (4.0.5) application with Spring Security (3.2.4) which includes CSRF protection which works fine. We are now adding the SAML security extension (spring-security-saml2-core 1.0.0) which causes an issue with CSRF protection. </p>
  
  <p>The metadata has been configured on SSOCircle and trying to access <code>http://localhost:8080/myapp</code> directs to the login page on SSOCircle. After authentication, the browser redirects to <code>http://localhost:8080/myapp/saml/SSO</code> and generates an error:</p>
  
  <p><strong>HTTP Status 403 - Expected CSRF token not found. Has your session expired?</strong></p>
  
  <p>If we turn off CSRF protection, everything works. How can we maintain CSRF protection and still use the SAML extension?</p>
  
  <p>Before setting up the SAML extension, we used a login form and CSRF protection worked and we did not receive an error on the login JSP and it did not have the token.</p>
  
  <p>Code before SAML:</p>
  
  <pre><code>@Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
      httpSecurity.authorizeRequests()
              .antMatchers("/login", "/login.request", "/logout").permitAll()
              .anyRequest()
                  .hasAnyAuthority("MyRole")
                      .and().formLogin()
              .loginPage("/login.request").loginProcessingUrl("/login")
              .failureUrl("/login.request?error").permitAll().and().logout()
              .logoutUrl("/logout").permitAll()
              .logoutSuccessUrl("/login.request");
  }
  </code></pre>
  
  <p>Code with SAML:</p>
  
  <pre><code>@Override
  protected void configure(HttpSecurity http) throws Exception {
      //http.csrf().disable();
  
      http.httpBasic().authenticationEntryPoint(samlEntryPoint());
  
      http.addFilterBefore(metadataGeneratorFilter(),
              ChannelProcessingFilter.class).addFilterAfter(samlFilter(),
              BasicAuthenticationFilter.class);
  
      http
          .authorizeRequests()
              .antMatchers("/error").permitAll()
              .antMatchers("/saml/**").permitAll()
              .anyRequest()
                  .hasAnyAuthority("MyRole")
              .anyRequest().authenticated();
  
      http.logout().logoutSuccessUrl("/");
  }
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>After re-enabling CSRF protection and setting logging to DEBUG, here are the logs that occur right after the successful authentication:</p>
  
  <pre><code>22.10.2014 16:54:17.374 [http-bio-8080-exec-8] DEBUG o.s.w.m.support.MultipartFilter -
                  Using MultipartResolver 'filterMultipartResolver' for MultipartFilter
  
  22.10.2014 16:54:17.377 [http-bio-8080-exec-8] DEBUG o.s.b.f.s.DefaultListableBeanFactory -
                  Returning cached instance of singleton bean 'filterMultipartResolver'
  
  22.10.2014 16:54:17.788 [http-bio-8080-exec-8] DEBUG o.s.w.m.support.MultipartFilter -
                  Request [/epass/saml/SSO] is not a multipart request
  
  22.10.2014 16:54:17.790 [http-bio-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
                  Checking match of request : '/saml/sso'; against '/resources/**'
  
  22.10.2014 16:54:17.791 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
                  /saml/SSO at position 1 of 14 in additional filter chain; firing Filter: 'MetadataGeneratorFilter'
  
  22.10.2014 16:54:17.793 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
                  /saml/SSO at position 2 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
  
  22.10.2014 16:54:17.795 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
                  /saml/SSO at position 3 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
  
  22.10.2014 16:54:17.797 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
                  HttpSession returned null object for SPRING_SECURITY_CONTEXT
  
  22.10.2014 16:54:17.798 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
                  No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@b08c9c9. A new one will be created.
  
  22.10.2014 16:54:17.800 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
                  /saml/SSO at position 4 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
  
  22.10.2014 16:54:17.801 [http-bio-8080-exec-8] DEBUG o.s.s.w.h.writers.HstsHeaderWriter -
                  Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@244a79ef
  
  22.10.2014 16:54:17.802 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
                  /saml/SSO at position 5 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
  22.10.2014 16:54:17.805 [http-bio-8080-exec-8] DEBUG o.s.security.web.csrf.CsrfFilter -
                  Invalid CSRF token found for `http://localhost:8080/myapp/saml/SSO`
  
  22.10.2014 16:54:17.807 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
                  SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
  
  22.10.2014 16:54:17.808 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter -
                  SecurityContextHolder now cleared, as request processing completed
  </code></pre>