How do I set up CSRF protection between an AngularJS front end and a Spring Boot REST backend? Let's take the http.post("/send-pin", JSONobject)...
call from the code below as an example.
I am getting the following error in the server logs when I try to call a Spring Boot REST service at the /send-pin
url pattern from an AngularJS front end method using http.post("/send-pin", JSONobject)...
:
Invalid CSRF token found for http://localhost:9000/send-pin
I read this other posting, which states that the csrf token needs to be set in the AngularJS code that makes the request, but the code in the link uses the syntax $(document).ajaxSend(function(e, xhr, options) {xhr.setRequestHeader('X-CSRF-TOKEN', token);});
, which does not directly paste into my code below. Also, the clode in the link takes data from a form, while my code takes data from an AngularJS controller. What specific changes need to be made to the code below so that the backend REST service will successfully process the request made by the AngularJS app to the REST service running at the localhost:9000/send-pin
url?
Here is the method in AngularJS:
$scope.login = function() {
auth.authenticate1($scope.credentials, function(authenticated1) {
if (authenticated1) {//authenticated1 returns true
var resultmessage = { "name": $scope.credentials.username };
$http.post('/send-pin', resultmessage).then(function(response) {//this call triggers the Invalid CSRF token error shown above
$scope.processStep = response.data.content;
auth.usrname = response.data.name;
});
$scope.error = false;
} else {
$scope.error = true;
}
})
}
Here is the UiApplication.java class that sets the SpringSecurity configuration:
@SpringBootApplication
@Controller
@EnableJpaRepositories(basePackages = "demo", considerNestedRepositories = true)
public class UiApplication extends WebMvcConfigurerAdapter {
// Match everything without a suffix (so not a static resource)
@RequestMapping(value = "/{[path:[^\\.]*}")
public String redirect() {
// Forward to home page so that route is preserved.
return "forward:/";
}
@RequestMapping("/user")
@ResponseBody
public Principal user(HttpSession session, Principal user) {
return user;
}
public static void main(String[] args) {
SpringApplication.run(UiApplication.class, args);
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US);
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private Users users;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(users);
}
}
@SuppressWarnings("deprecation")
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests()
.antMatchers("/check-pin").permitAll()
.antMatchers("/index.html", "/", "/login", "/someotherrurl")
.permitAll().anyRequest().authenticated().and().csrf()
.csrfTokenRepository(csrfTokenRepository()).and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}
private Filter csrfHeaderFilter() {
return new 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);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
}
Here is the error log from the Linux terminal which prints out while the REST service is running:
2016-01-15 13:15:27.704 DEBUG 7031 --- [nio-9000-exec-1] tRepository$SaveToSessionResponseWrapper : Skip invoking on
2016-01-15 13:15:27.704 DEBUG 7031 --- [nio-9000-exec-1] tRepository$SaveToSessionResponseWrapper : Skip invoking on
2016-01-15 13:15:27.704 DEBUG 7031 --- [nio-9000-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2016-01-15 13:15:27.704 DEBUG 7031 --- [nio-9000-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/css/**'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/js/**'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/images/**'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/**/favicon.ico'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/error'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/autoconfig']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/autoconfig'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/autoconfig/**']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/autoconfig/**'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/autoconfig.*']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/autoconfig.*'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/autoconfig/']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/autoconfig/'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/metrics']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/metrics'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/metrics/**']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/metrics/**'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/metrics.*']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/metrics.*'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/metrics/']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/metrics/'
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/trace']
2016-01-15 13:15:27.713 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/trace'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/trace/**']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/trace/**'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/trace.*']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/trace.*'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/trace/']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/trace/'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/env']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/env'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/env/**']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/env/**'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/env.*']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/env.*'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/env/']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/env/'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/health']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/health'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/health/']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/health/'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/mappings']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/mappings'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/mappings/**']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/mappings/**'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/mappings.*']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/mappings.*'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/mappings/']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/mappings/'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/dump']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/dump'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/dump/**']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/dump/**'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/dump.*']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/dump.*'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/dump/']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/dump/'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/error']
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/error'
2016-01-15 13:15:27.714 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/error/']
2016-01-15 13:15:27.715 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/error/'
2016-01-15 13:15:27.715 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/beans']
2016-01-15 13:15:27.716 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/beans'
2016-01-15 13:15:27.716 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/beans/**']
2016-01-15 13:15:27.716 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/beans/**'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/beans.*']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/beans.*'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/beans/']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/beans/'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/info']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/info'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/info/']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/info/'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/configprops']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/configprops'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/configprops/**']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/configprops/**'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/configprops.*']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/configprops.*'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/configprops/']
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/send-pin'; against '/configprops/'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy : /send-pin at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy : /send-pin at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@d8393cb4: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d8393cb4: Principal: org.springframework.security.core.userdetails.User@63d9948c: Username: another@shirt.com; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffdaa08: RemoteIpAddress: 127.0.0.1; SessionId: 61483B5DDC3336EC44BF528C97749AA9; Granted Authorities: ROLE_USER'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy : /send-pin at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-01-15 13:15:27.717 DEBUG 7031 --- [io-9000-exec-10] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@4f81666
2016-01-15 13:15:27.723 DEBUG 7031 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy : /send-pin at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
2016-01-15 13:15:27.724 DEBUG 7031 --- [io-9000-exec-10] o.s.security.web.csrf.CsrfFilter : Invalid CSRF token found for http://localhost:9000/send-pin
2016-01-15 13:15:27.725 DEBUG 7031 --- [io-9000-exec-10] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed