I have an inMemoryAuthentication configuration that works:
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(
AuthenticationManagerBuilder authenticationManagerBuilder)
throws Exception {
authenticationManagerBuilder //
.inMemoryAuthentication() //
.withUser("employee") //
.password("employee") //
.roles("RoleEmployee")
;
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// @formatter:off
httpSecurity
.authorizeRequests()
.antMatchers("/login","/login.request","/logout").permitAll()
.anyRequest().hasRole("RoleEmployee")
.and()
.formLogin()
.loginPage("/login.request")
.loginProcessingUrl("/login")
.failureUrl("/login.request?error")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.permitAll()
.logoutSuccessUrl("/login.request")
;
// @formatter:on
}
}
I want to now use Siteminder authentication and changed this to:
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private PreAuthenticatedAuthenticationProvider preAuthenticatedProvider;
public WebSecurityConfiguration() {
super();
userDetailsService = new CustomUserDetailsService();
UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> wrapper = new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(
userDetailsService);
preAuthenticatedProvider = new PreAuthenticatedAuthenticationProvider();
preAuthenticatedProvider.setPreAuthenticatedUserDetailsService(wrapper);
}
@Override
protected void configure(
AuthenticationManagerBuilder authenticationManagerBuilder)
throws Exception {
// @formatter:off
authenticationManagerBuilder //
.authenticationProvider(preAuthenticatedProvider);
// @formatter:on
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// @formatter:off
RequestHeaderAuthenticationFilter siteMinderFilter = new RequestHeaderAuthenticationFilter();
siteMinderFilter.setAuthenticationManager(authenticationManager());
httpSecurity
.addFilter(siteMinderFilter)
.authorizeRequests()
.antMatchers("/login","/login.request","/logout").permitAll()
.anyRequest().hasRole("RoleEmployee")
.and()
.formLogin()
.loginPage("/login.request")
.loginProcessingUrl("/login")
.failureUrl("/login.request?error")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.permitAll()
.logoutSuccessUrl("/login.request")
;
// @formatter:on
}
}
For now CustomUserDetailsService always returns a user with the employee role:
public class CustomUserDetailsService implements
UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("RoleEmployee");
authorities.add(authority);
UserDetails user = new User(username, "password", authorities);
return user;
}
}
When I test this, the SM_USER header is correctly passed in and I can see in the debugger that CustomUserDetailsSerice is correctly called, but a 403 Forbidden status is returned for any page that I was previously able to access successfully under the old configuration.
Is there something wrong with this configuration?
Oftentimes asking the question helps answer it.
Changing:
anyRequest().hasRole("RoleEmployee")
to:
anyRequest().hasAuthority("RoleEmployee")
fixed it.