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.
Change
to
This means any URL that doesn't match what you have explicitly defined will require authentication.