12

I am trying to implement the impersonate using SwitchUserFilter in Spring but I'm getting an error. The project runs good without this implementation. Also the project is using Java annotations not xml configuration and has SecureAuth authentication. And the parts involved in the code into the SecurityConfig class is:

@Configuration
@ComponentScan(basePackages = {"com.project.*"})
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@PropertySource("classpath:app.properties")
@Import({TransactionManagersConfig.class, MailConfig.class})
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private SwitchUserFilter switchUserFilter;

  @Autowired
  protected AuthenticationSuccessHandler authenticationSuccessHandler;

  @Bean
  public UserDetailsService userDetailsServiceBean() {
    try {
        return super.userDetailsServiceBean();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
  }

  @Bean
  public SwitchUserFilter switchUserFilter() {
    SwitchUserFilter switchUserFilter = new SwitchUserFilter();
    switchUserFilter.setUserDetailsService(userDetailsServiceBean());
    switchUserFilter.setUsernameParameter("username");
    switchUserFilter.setSwitchUserUrl("/switch");
    switchUserFilter.setExitUserUrl("/exit");
    switchUserFilter.setTargetUrl("/");

    return switchUserFilter;
  }

  //more beans

  @Override
  protected void configure(HttpSecurity http) throws Exception {
        http
                .headers().disable();
        http    //SAML CONFIG
                .httpBasic()
                .authenticationEntryPoint(samlEntryPoint()).and()
                .addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
                .addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
        http    //DISABLE CROSS-SITE REQUEST FORGERY
                .csrf()
                .disable();
                //Impersonate Interceptor
        http
                .addFilterAfter(switchUserFilter(), FilterSecurityInterceptor.class);
        http
                .authorizeRequests()
                .antMatchers("/impersonate").permitAll()
                .antMatchers("/api/**").permitAll()
                .antMatchers("/#/**").permitAll()
                .antMatchers("/switch").permitAll()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/index")
                .permitAll().successHandler(authenticationSuccessHandler);
        http
                .logout().logoutSuccessUrl(env.getProperty("realm.url.restart"));
        http
                .exceptionHandling().accessDeniedPage("/error?code=403&error=Access Denied&detail=You are not authorized to access.");

     }    

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
       return super.authenticationManagerBean();
    }    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .authenticationProvider(samlAuthenticationProvider());
    }

    @Override
    public void configure(WebSecurity webSecutity) throws Exception {
        webSecutity
                .ignoring().antMatchers("/resources/**");
    }
}

Error:

java.lang.IllegalStateException: UserDetailsService is required.
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.java:393)
    at org.springframework.security.web.authentication.switchuser.SwitchUserFilter.attemptSwitchUser(SwitchUserFilter.java:209)
    at org.springframework.security.web.authentication.switchuser.SwitchUserFilter.doFilter(SwitchUserFilter.java:155)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at

My url stops on:

http://localhost:8080/switch?j_username=angel_cuenca

If you need more part of the code, pleasure to share.

Angel Cuenca
  • 1,637
  • 6
  • 24
  • 46
  • @dur yes when I debug and evaluate `super.userDetailsServiceBean()` contains `null` in the field `delegate` – Angel Cuenca Apr 21 '17 at 17:20
  • You didn't configure a `UserDetailsService`, so it is `null`. You have to configure one. – dur Apr 24 '17 at 14:08
  • Sorry, I have no experience with Spring Security SAML, so I don't know how to configure the `UserDetailsService`. Maybe this [link](https://www.dontpanicblog.co.uk/2014/05/07/saml-based-single-sign-on-sso-in-spring-security-applications/) helps. – dur Apr 24 '17 at 14:24
  • The problem is, that SAML uses his own interface `SAMLUserDetailsService` which is not compatible to Spring Security's `UserDetailsService`. So you have no Spring Security `UserDetailsService`. Maybe the only way is to implement your own `UserDetailsService` to use with `SwitchFilter`. – dur Apr 25 '17 at 15:05

1 Answers1

-1

Can you try to set the userDetailsService implementation to the configuration, like in this ?

I don't see in your configuration:

auth.userDetailsService(userService);
Community
  • 1
  • 1
Erwin
  • 32
  • 4
  • Still not working. When I add `auth.userDetailsService(userService);` to the `configure(AuthenticationManagerBuilder auth)` give to me another error `switch java.lang.StackOverflowError` which redirect me to this question (http://stackoverflow.com/questions/30766106/spring-security-java-lang-stackoverflowerror-exception-after-all-providers) and the solution for this error was removed userDetailService recently added. So I don't know.. – Angel Cuenca May 01 '17 at 19:34
  • Sure. You can see here, this is my current code (https://github.com/angelcuenca/stackoverflow/blob/master/SecurityConfig.java) line 528. You do can see what's the problem ? – Angel Cuenca May 01 '17 at 19:53
  • I think the issue is the same with the link you provide. I declare my UserDetailsService implementation in another class which implement the loadUserByUsername method. – Erwin May 01 '17 at 20:05
  • [Here](https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#userdetailsservice-implementations). Hope this help. – Erwin May 01 '17 at 20:10
  • Not find the solution yet. And what was result for the implementation in another class ? – Angel Cuenca May 02 '17 at 15:31
  • Actually I'm not reading about the SwitchUserFilter, sorry. But [here](http://docs.spring.io/autorepo/docs/spring-security/4.0.3.RELEASE/apidocs/index.html?org/springframework/security/web/authentication/switchuser/SwitchUserFilter.html) I check you need to provide value for the user, the same like if it don't use SwitchUserFilter. I don't see your userDetailsService load the value? CMIIW. – Erwin May 02 '17 at 16:49