Spring Security Java Config for Siteminder

Paul Croarkin picture Paul Croarkin · Apr 3, 2014 · Viewed 8.7k times · Source

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?

Answer

Paul Croarkin picture Paul Croarkin · Apr 3, 2014

Oftentimes asking the question helps answer it.

Changing:

anyRequest().hasRole("RoleEmployee")

to:

anyRequest().hasAuthority("RoleEmployee")

fixed it.