'How does one use different session creation policies for UI and REST endpoints with Spring Security?

I have an application that contains both a UI and some REST endpoints. The UI uses SAML login (the old Spring Security SAML extension) and the REST endpoints using a custom authentication. The REST endpoints are only called by external applications. For the REST endpoints ("/api/**") I have stated a stateless session creation policy and for the rest of the endpoint no session creation policy at all (I also tried with ALWAYS as in the below example).

Prior to some Spring Boot version, not sure which, this worked. Currently I'm using Spring Boot v.2.6.1. The UI endpoint got the authentication object from the Http session.

But now it doesn't work. The security context object cannot be found in the Http session using the default HttpSessionSecurityContextRepository implementation. It is saved but it can't be restored.

So is it possible to use two session creation policy, one for the REST and the other for the UI part, or should this be handled in a different way? Now it seems that the stateless session creation policy is also used by the UI, which is not intended. I'm using two WebSecurityConfigurerAdapter classes; one for the API and the other for the UI. After a successful SAML login the redirect URL now contains the ";jsessionid=6051854D94A0771BB9B99FE573AA4DFD" parameter. Probably because of the stateless policy...?

    protected void configure(HttpSecurity http) throws Exception {

        List<AbstractAuthenticationProcessingFilter> authFilters = new ArrayList<>();
        authFilters.add(new OAuthMacAuthenticationProcessingFilter(authenticationManager(), this.properties));

        ApiAuthenticationProcessingFilter apiAuthenticationProcessingFilter = new ApiAuthenticationProcessingFilter(authenticationManager(),authFilters);

        http
        .csrf()
        .disable()
        .antMatcher("/api/**")
        .authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
        .exceptionHandling()
        .authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
        .and()
        .addFilterBefore(apiAuthenticationProcessingFilter, BasicAuthenticationFilter.class)
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

and for the UI part

    protected void configure(HttpSecurity http) throws Exception {

        http.securityContext().securityContextRepository(customSessionSecurityContextRepository);

        http
        .httpBasic()
        .authenticationEntryPoint(samlEntryPoint());

        http
        .addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class);

        var auth = http
                .authorizeRequests()
                .antMatchers("/saml/**").permitAll()
                .antMatchers("/loggedout/**").permitAll()
                .antMatchers("/error").permitAll();
                
        auth
        .anyRequest()
        .authenticated();

        http.csrf().disable();

        http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.ALWAYS);

        http.headers().frameOptions().sameOrigin();

        http.exceptionHandling().accessDeniedHandler(this.accessDeniedHandler());

        http
        .logout()
        .disable();    // The logout procedure is already handled by SAML filters.
    }


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source