dlemp
dlemp

Reputation: 23

CAS singleSignOutFilter not Catching User Logout

I've been working on a Spring Boot app that uses CAS for SSO for days now. Single sign on works great! And I have a logout button within the app that works as well. The problem I'm running in to is Single Logout (SLO) does not work. Meaning when I log out of another application, SLO works everywhere except for this app. When I log out of this app, though, I am logged out of everything else. So it seems like this app here isn't listening for when an SSO session is ended.

Our CAS is version 6.5, and I'm using spring-security-cas version 5.7.2.

Here's my WebSecurityConfig:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  private Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
  private SingleSignOutFilter singleSignOutFilter;
  private LogoutFilter logoutFilter;
  private CasAuthenticationProvider casAuthenticationProvider;
  private ServiceProperties serviceProperties;

@Autowired
  public WebSecurityConfig(SingleSignOutFilter singleSignOutFilter, LogoutFilter logoutFilter,
                           CasAuthenticationProvider casAuthenticationProvider,
                           ServiceProperties serviceProperties) {
    this.logoutFilter = logoutFilter;
    this.singleSignOutFilter = singleSignOutFilter;
    this.serviceProperties = serviceProperties;
    this.casAuthenticationProvider = casAuthenticationProvider;
  }

@Override
  protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable();  //for testing

    http.authorizeRequests()
      .antMatchers("/login/cas","/styles.css").permitAll()    
      .antMatchers("/profile").hasAuthority(appAdmin) 
      .antMatchers( "/**").hasAnyAuthority(appUser)    

            .and()
            .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)
            .addFilterBefore(logoutFilter, LogoutFilter.class)                 
            .exceptionHandling().accessDeniedPage("/403")                 
            .authenticationEntryPoint(authenticationEntryPoint()
      );
  }
@Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(casAuthenticationProvider);
  }

  @Bean
  @Override
  protected AuthenticationManager authenticationManager() throws Exception {
    return new ProviderManager(Collections.singletonList(casAuthenticationProvider));
  }

  public AuthenticationEntryPoint authenticationEntryPoint() {
    CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
    entryPoint.setLoginUrl(casServer+"/cas/login");    
    entryPoint.setServiceProperties(serviceProperties);
    return entryPoint;
  }
}

And here's my Cas App:

@EntityScan
@SpringBootApplication ()
public class CasSecuredApplication extends SpringBootServletInitializer {

  private static final Logger logger = LoggerFactory.getLogger(CasSecuredApplication.class);

  public static void main(String... args) {
    SpringApplication.run(CasSecuredApplication.class, args);
  }

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    return builder.sources(CasSecuredApplication.class);
  }

  @Bean
  public CasAuthenticationFilter casAuthenticationFilter(
    AuthenticationManager authenticationManager,
    ServiceProperties serviceProperties) throws Exception {
    CasAuthenticationFilter filter = new CasAuthenticationFilter();
    filter.setAuthenticationManager(authenticationManager);
    filter.setServiceProperties(serviceProperties);
    return filter;
  }
@Bean
  public ServiceProperties serviceProperties() {
    logger.info("service properties");
    ServiceProperties serviceProperties = new ServiceProperties();
    serviceProperties.setService(appServer+contextPath+"/login/cas"); 
    serviceProperties.setSendRenew(false);
    return serviceProperties;
  }

  @Bean
  public TicketValidator ticketValidator() {
    return new Cas30ServiceTicketValidator(casServer+"/cas/") ;}   

  @Autowired
  private AuthenticationUserDetailsService UserDetail;

  @Bean
  public CasAuthenticationProvider casAuthenticationProvider(
    TicketValidator ticketValidator,
    ServiceProperties serviceProperties) {
    CasAuthenticationProvider provider = new CasAuthenticationProvider();
    provider.setServiceProperties(serviceProperties);
    provider.setTicketValidator(ticketValidator);
    provider.setAuthenticationUserDetailsService(UserDetail);
    provider.setKey("CAS_PROVIDER_LOCALHOST_8900") 
    ;
    return provider;
  }

  @Bean
  public SecurityContextLogoutHandler securityContextLogoutHandler() {
    return new SecurityContextLogoutHandler();
  }

  @Bean
  public LogoutFilter logoutFilter() {
    LogoutFilter logoutFilter = new LogoutFilter(casServer+"/cas/logout", securityContextLogoutHandler());     
    logoutFilter.setFilterProcessesUrl("/logout/cas");
    return logoutFilter;
  }
@Bean
  public SingleSignOutFilter singleSignOutFilter() {
    SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
    singleSignOutFilter.setLogoutCallbackPath("/exit/cas");
    singleSignOutFilter.setIgnoreInitConfiguration(true);
    return singleSignOutFilter;
  }
  @EventListener
  public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(HttpSessionEvent event) {
    return new SingleSignOutHttpSessionListener();
  }
  @Bean
  public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
  };
    return tomcat;
  }
}

Upvotes: 0

Views: 483

Answers (1)

Creamstout10
Creamstout10

Reputation: 513

If CAS is configured for Single Log Out (SLO) you need to register this service for SLO and specify if it is a Back Channel Logout or a Front Channel Logout.

Then in the service you need to expose an endpoint (Back Channel) or a page (Front Channel) that will kill the session. When the user is directed to CAS for logout it will fire logout requests.

https://apereo.github.io/cas/6.5.x/installation/Logout-Single-Signout.html

Upvotes: 0

Related Questions