1
votes

Basically I cannot get spring-boot oauth2 integration to work with spring-session.

I created an issue in spring-boot's issue tracker: https://github.com/spring-projects/spring-boot/issues/4360

I made a repo to demonstrate this problem

https://github.com/sloppycoder/spring-session-oauth-problem

there're 2 modules:

  • auth-server is the oauth2 authorization server. to run it, just mvn. the server will be at http://localhost:19999/uaa
  • web-app is the web application that uses the auth-server for single sign-on. mvn will start the app on http://localhost:8080

My sso logout logic works like this:

  1. click on "Logout" button will do a POST to http://localhost:19999/uaa/logout, with passing the URL to redirect to, http://localhost:8080/ssologout, after successful logout.
  2. auth-server logout and redirect to http://localhost:8080/ssologout
  3. http://localhost:8080/ssologout then POST to http://localhost:8080/logout
  4. (default spring-security behavior) after logout, redirect to http://localhost:8080/login?logout
  5. http://localhost:8080/login?logout redirect to http://localhost:19999/uaa/login and prompt user to login again.

However after I bring in the spring-session, step #5 is not happening. the browser goes directly to web-app /dashboard.

make sure you start your local redis daemon before running the sos-spring-session branch.

I created 2 branches to show the different behavior:

  1. sso-only. spring-boot integrates with auth-server and things work fine.
  2. sso-spring-sesson. logout does not work.

github compare shows the difference.

I'll appreciate any advise and suggestions on how to solve this.

2

2 Answers

1
votes

I had similar problem on spring-boot 1.3.0.RC1, spring-session and redis.

spring-boot 1.3.0.RC1 : ClassCastException in getting oauth2 user info from session persisted in Redis

It may work if you change filter order as

'requestContextFilter' < 'OAuth2ClientContextFilter' < 'springSessionRepositoryFilter'

@Bean
@ConditionalOnMissingBean(RequestContextFilter.class)
public RequestContextFilter requestContextFilter() {

  return new RequestContextFilter();
}

@Bean
public FilterRegistrationBean requestContextFilterChainRegistration(
  @Qualifier("requestContextFilter") Filter securityFilter) {

  FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
  registration.setName("requestContextFilter");

  // note : must previous order of oAuth2ClientContextFilter
  registration.setOrder(SessionRepositoryFilter.DEFAULT_ORDER + 1);

  return registration;
}

@Bean
public FilterRegistrationBean sessionRepositoryFilterRegistration(
  SessionRepositoryFilter sessionRepositoryFilter) {

  FilterRegistrationBean registration = new FilterRegistrationBean(sessionRepositoryFilter);
  registration.setName("springSessionRepositoryFilter");

  // note : must following order of oAuth2ClientContextFilter
  registration.setOrder(Integer.MAX_VALUE - 1);

  return registration;
}

also you may need to remove dependency org.springframework.boot:spring-boot-devtools

related to https://github.com/spring-projects/spring-boot/issues/3805


postscript: for spring-boot 1.3.3.RELEASE

spring-session, redis, spring-security-oauth2 works below filter order.

# logs on bootRun task
Mapping filter: 'characterEncodingFilter' to: [/*]
Mapping filter: 'springSessionRepositoryFilter' to: [/*]
Mapping filter: 'requestContextFilter' to: [/*]
Mapping filter: 'OAuth2ClientContextFilter' to: [/*]
Mapping filter: 'springSecurityFilterChain' to: [/*]
Mapping servlet: 'dispatcherServlet' to [/]

current required setting is below.

@Bean
@ConditionalOnMissingBean(RequestContextFilter.class)
public RequestContextFilter requestContextFilter() {
  return new RequestContextFilter();
}

@Bean
public FilterRegistrationBean requestContextFilterChainRegistration(
  @Qualifier("requestContextFilter") Filter securityFilter) {

  FilterRegistrationBean registration = 
    new FilterRegistrationBean(securityFilter);

  registration.setName("requestContextFilter");

  // note : must to be following order of springSessionRepositoryFilter
  registration.setOrder(SessionRepositoryFilter.DEFAULT_ORDER + 1);

  return registration;
}
1
votes

There are quite a few issues with that code, but the one that stops it working with Spring Session is that the two apps are sharing a cookie. The context-path is "/" for the "main" webapp, so the auth server tries to use the same cookie when it is running on the same host. It doesn't matter when you use a local session, but when you use a distributed session you mess up the state when the 2 apps try to share the same session. You can fix it by using a server.context-path in the webapp (e.g. /app) and making corresponding changes to your HTML etc. to make sure that the browser follows paths back to there.