psheffield
psheffield

Reputation: 21

Spring Security SAML Extension with Remember Me functionality across multiple tomcat webapps

I have 2 spring applications that are running side by side on a tomcat server. I am using the token based RememberMeAuthenticationProvider with a custom UserDetailsService so I only authenticate the users once and they can navigate between the 2 applications without having to reauthenticate.

Along with the normal username/password login process I have configured the spring saml extension to authenticate users on my application (SP) using an external IdP. I use the SAMLAuthenticationProvider with a custom SAMLUserDetailsService to match the saml assertion username to a user in my database and they are authenticated in one of my applications. The problem I am having is the user is not authenticated on my second application. It keeps asking for a username and password when navigating to the second application, as I would expect because there is no remember me token/cookie configured for the SAMLAuthenticationProvider.

Is there any way I can use token based remember me services with the SAMLUserDetailsService?

Upvotes: 2

Views: 720

Answers (3)

OrangeDog
OrangeDog

Reputation: 38797

The key is to ensure SAMLProcessingFilter.rememberMeServices has been set. This is a little tricky because none of the default rememberMe() components are exposed. Here's a possible solution.

@Autowired
public void configureRememberMe(
        @Qualifier(BeanIds.SPRING_SECURITY_FILTER_CHAIN) Filter securityChain,
        List<SAMLProcessingFilter> filters
) {
    RememberMeServices rememberMe = ((FilterChainProxy) securityChain).getFilterChains().stream()
            .flatMap(chain -> chain.getFilters().stream())
            .filter(RememberMeAuthenticationFilter.class::isInstance)
            .map(RememberMeAuthenticationFilter.class::cast)
            .findAny()
            .map(RememberMeAuthenticationFilter::getRememberMeServices)
            .orElseGet(NullRememberMeServices::new);

    filters.forEach(filter -> filter.setRememberMeServices(rememberMe));
}

If you construct your own RememberMeServices then just inject it directly rather than fishing it out of the filter chain.

Next problem is if you don't have .alwaysRemember(). I don't think there's any way to pass a request parameter through an IdP. You're going to have to either extend a RememberMeServices and override rememberMeRequested based on some external context, or extend WebSSOProfile to add the remember-me parameter dynamically to the binding URLs.

Upvotes: 0

psheffield
psheffield

Reputation: 21

I ended up using the SAMLAuthenticationProvider and manually creating a remember me token (by copying spring source code under the RememberMeAuthenticationProvider) when a user successfully authenticates.

I couldn't find a way to elegantly combine the features of the SAMLAuthenticationProvider and the RememberMeAuthenticationProvider through spring configuration, but it works now.

Upvotes: 0

martin samm
martin samm

Reputation: 137

have you configured both apps to use the same session store? are they on the same domain/subdomain so they can share the auth cookie? i would set one of the apps to be the (only) auth point and set the login from the second to go to it for auth.

Upvotes: 0

Related Questions