Spring Security Java Config for Siteminder
Asked Answered
R

1

9

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?

Rainarainah answered 3/4, 2014 at 16:59 Comment(3)
What does the debug log say?Osmunda
Hey Paul, I have a question regarding this. Did you set up a siteminder policy agent on the web server ? Or do you have your own login page and when user clicks login, are you doing a POST request to siteminder from your application ? I see you have configured formLogin and the request url to /login.request. I just want to understand what does it map to . Thanks in advance.Hoes
We have since switched to SAML, but to answer your question: the login.request mapping was removed after moving away from in memory authentication. It was still there for a bit as we were frequently switching back and forth from in memory to SM authentication for a while.Rainarainah
R
7

Oftentimes asking the question helps answer it.

Changing:

anyRequest().hasRole("RoleEmployee")

to:

anyRequest().hasAuthority("RoleEmployee")

fixed it.

Rainarainah answered 3/4, 2014 at 17:14 Comment(1)
Thanks for posting this. This really helped me get over the initial hurdle. [I have documented the way I have used this in my project]( github.com/numberformat/northwind/blob/master/documentation/…)Akilahakili

© 2022 - 2024 — McMap. All rights reserved.