I'm trying to configure Spring Security via Java Config to handle two kinds of authentication on my app: form based (user login) and token based (REST api).
The form configuration is straighforward, except the part where I had to create my own SecuritySocialConfigurer
(basically a copy of SpringSocialConfigurer
with a custom authentication success handler that generates a JWT token and sets a cookie with it in the response).
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth
.userDetailsService(userDetailsService())
.passwordEncoder(NoOpPasswordEncoder.getInstance());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/img/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/signin")
.loginProcessingUrl("/signin/authenticate")
.failureUrl("/signin?param.error=bad_credentials")
.and()
.logout()
.logoutUrl("/signout")
.deleteCookies("JSESSIONID")
.and()
.authorizeRequests()
.antMatchers("/admin/**", "favicon.ico", "/public/**", "/auth/**", "/signin/**").permitAll()
.antMatchers("/**").hasRole("USER")
.and()
.rememberMe()
.and()
.apply(new MilesSocialSecurityConfigurer());
}
When only this configuration is in play, I'm able to access http://localhost:8080
and be redirected to http://localhost:8080/signin
to perform signin. After successful signin I check that the JWT token cookie is present.
The second security config purpose is to check the presence of the JWT token when the REST api is called.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.antMatcher("/api/**")
.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("favicon.ico", "/public/**", "/auth/**", "/signin/**").permitAll()
.antMatchers("/**").authenticated()
;
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
JwtAuthenticationFilter filter = new JwtAuthenticationFilter("/api/**");
filter.setAuthenticationSuccessHandler(jwtAuthenticationSuccessHandler);
filter.setAuthenticationManager(apiAuthenticationManager());
return filter;
}
@Bean
public ProviderManager apiAuthenticationManager() {
return new ProviderManager(Arrays.asList(jwtAuthenticationProvider));
}
JwtAuthenticationProvider
is a class that parses a JWT token and generates an UserDetails
object or throws an AuthenticationException
if a token does not exist or is invalid.
When this second config is in place, I'm unable to navigate to http://localhost:8080
(or /signin
) to initiate the signin proccess - the browser returns a ERR_TOO_MANY_REDIRECTS.
I tried some things without any success. Any clue about what is going on would be much appreciated.
Thanks.