My Java application uses spring security and Saml2 as a service provider. I am able to integrate with the identity provider and get saml assertions correctly. I want to avoid using JSESSIONID for overhead in my application since I have custom session attribute x-auth as cookie.

But, I see that a session is created every time and remains persistent till the user sign's out.

I tried adding the below line to the configure method, http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

But, with this setting I am always being asked to login to Identity Provider.

If I login, it comes back to the page asking me to login again in a loop.

I am not sure if this is the correct behaviour when disabling sessions.

Can anyone provide me with the right approach to use stateless sessions with below code ?


 @Bean
  SecurityFilterChain configure(HttpSecurity http) throws Exception {
    OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider();
    authenticationProvider.setResponseAuthenticationConverter(createTokenCredential());

    Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationRepository,
        new OpenSamlMetadataResolver());
    http.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
    loginSuccessHandler.setTargetUrlParameter(Saml2ParameterNames.RELAY_STATE);

    http.authorizeHttpRequests(requests -> requests
            .requestMatchers("/saml2/service-provider-metadata/**")
            .permitAll()
        ).addFilterAfter(authTokenSessionRestore, SecurityContextHolderFilter.class)
        .saml2Login((saml2) -> saml2
            .loginProcessingUrl("/saml/SSO")
            .authenticationManager(new ProviderManager(authenticationProvider))
            .relyingPartyRegistrationRepository(relyingPartyRegistrationRepository)
            .successHandler(loginSuccessHandler)
            .failureHandler(loginFailureHandler)

        ).saml2Logout(withDefaults())
        .logout().logoutSuccessUrl("/login")
        .logoutSuccessHandler(logoutSuccessHandler);



    http.sessionManagement(session -> {
          session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }); // dont create a session for this configuration
}

Comment From: sumeetpri

@marcusdacoregio @sjohnr - Looking forward for your expert input on how to achieve IDP login keeping session stateless.

Comment From: marcusdacoregio

Hi, @sumeetpri.

Spring Security SAML 2.0 Login uses a Saml2AuthenticationRequestRepository to save the authentication request in the session before redirecting you to the IdP. If there is no session, there is no way for Spring Security to "remember" that request, and, therefore, authenticate the user. I believe this is the root of the problem in your approach.

As an alternative, you can provide a custom implementation of Saml2AuthenticationRequestRepository that stores the request in a cookie and loads it when the request comes back.

Comment From: sumeetpri

I attempted the try again, using the same code as mentioned above, and this time it worked successfully. The issue may have been something else that I didn't notice initially. Interestingly, it functions correctly with a STATELESS session. How can we confirm that the application is indeed operating in a stateless manner ? Are you sure Spring Security SAML 2.0 Login will not work if SessionCreationPolicy is STATELESS ? The below code works for me and I am able to login to okta IDP and logout also.

http.authorizeHttpRequests(requests -> requests
            .requestMatchers(SAML2_SERVICE_PROVIDER_METADATA, SAML2_IDP_DISCOVERY)
            .permitAll()
        )
        .addFilterAfter(authTokenSessionRestore, SecurityContextHolderFilter.class)
     .saml2Login((saml2) -> saml2
            .loginProcessingUrl(SAML2_ASSERTION_CONSUMER_SERVICE_URL)
            .authenticationManager(new ProviderManager(authenticationProvider))
            .relyingPartyRegistrationRepository(relyingPartyRegistrationRepository)
            .successHandler(loginSuccessHandler)
            .failureHandler(loginFailureHandler)
        ).saml2Logout(Customizer.withDefaults())
        .logout(logout->{
            logout
                .deleteCookies("JSESSIONID")
                .logoutRequestMatcher(new AntPathRequestMatcher(LOGOUT_URL))
                .logoutSuccessUrl(contextPath)
                .addLogoutHandler(logoutSuccessHandler)
                .invalidateHttpSession(true);
          });

    http.sessionManagement(session -> {
      session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    });

Comment From: sumeetpri

@marcusdacoregio looking forward for your input.

Comment From: sumeetpri

@marcusdacoregio looking forward for your input.