Search code examples
javaspring-bootspring-securityjwt

Clarification on spring security management of authenticated sessions


I follow-up my previous question with a different and more specific doubt, consider the following scenario:

  • I am currently running an Oauth2 resource server using spring security 6. The client app sends a JWT token with some claims that gets correctly validated by my server.
  • At this point, spring security should open a session (or use an existing one) and store the authentication info in the session cookie
  • All subsequent requests from that specific client application should now be authenticated, without repeating the JWT validation, until the session expires

However, this does not seem to be the case, as the requests that contain the session header but do not bear the JWT are unhautorized, this is my filter chain:

@Bean
public SecurityFilterChain oauth2Chain(HttpSecurity http) throws Exception {
    http
            // persist authentication
            // // session creation policy
            // .sessionManagement(httpSecuritySessionManagementConfigurer ->
            // httpSecuritySessionManagementConfigurer
            // .sessionCreationPolicy(SessionCreationPolicy.IF_NEEDED))
            // persist context
            .securityContext((securityContext) -> securityContext
                    .securityContextRepository(new HttpSessionSecurityContextRepository()))
            // default policy: jwt oauth2 on all requests
            .authorizeHttpRequests(authorize -> authorize
                    .anyRequest().authenticated())
            .oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));
    return http.build();
}

I also tried the default first:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(authorize -> authorize
            .anyRequest().authenticated()
        )
        .oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));
    return http.build();
}

What is the correct way to make the client authenticate only once per session? Should I explicitly create the session at some point? I only have:

@EnableSpringHttpSession
@Configuration
public class HtmlSessionConfig {
    @Bean
    public MapSessionRepository sessionRepository() {
        return new MapSessionRepository(new ConcurrentHashMap<>());
    }
}

Solution

  • Only two sessions are used for a user in an OAuth2 system:

    • on the authorization server
    • on the client (some server-side state is necessary during the authorization code flow to store some verifiers like nonce or PKCE token if used, and after the flow completed, to store tokens)

    But on resource servers, the "state" is sent by the client with each request (token claims). So, it is the expected behavior that an access token is sent with each request to a resource server and that this resource server validates it for each request (decodes and validates a JWT or introspect any kind of token).