Java 11 SpringBoot 2.5.4

Hi,

We have had a service using significant amounts of heap space. We have managed to get a heap dump and it looks like the map in CachingOperationInvoker is enormous. We are using spring security to secure the endpoints in the service but the health endpoint does not require authentication.

The spring security configuration,

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class JwtWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

  @Autowired private JwtAuthenticationConverter jwtAuthenticationConverter;

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests(authorize -> authorize.antMatchers("/v*/**").authenticated())
        .authorizeRequests(authorize -> authorize.anyRequest().permitAll())
        .csrf()
        .disable()
        .oauth2ResourceServer()
        .jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(jwtAuthenticationConverter));
  }
}

Where JwtAuthenticationConverter is defined in another @Configuration class and uses the JwtGrantedAuthoritiesConverter to set the prefix and location of the claims in the jwt

  @Bean
  public JwtAuthenticationConverter getJwtAuthenticationConverter() {
    JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter =
        new JwtGrantedAuthoritiesConverter();
    jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(ROLES_CLAIM_NAME);
    jwtGrantedAuthoritiesConverter.setAuthorityPrefix(ROLE_PREFIX);
    JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
    jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);

    return jwtAuthenticationConverter;
  }

When a non-authenticated user calls the health endpoint the cache in the CachingOperationInvoker is used correctly because the principal is null. However, if a user calls the health endpoint and provides a jwt the Principal is not null and there is a cache miss. In this case the Principal is a org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken and every time the user refreshes their token the hash of the JwtAuthenticationToken is different which means that the CacheKey hash is different hence the cache miss. In our situation this results in the CachingOperationInvoker.cachedResponses growing and growing with each authenticated request.

Honestly I don't know if this is genuinely a memory leak / issue or is caused by us doing something stupid through our configuration. I'd love to know your thoughts and to get some advice please.

Thanks,

Andy

Comment From: snicoll

Thanks for the report. It looks to me that, at the very least, we should have some sort of automatic expiration of cache entries.

Comment From: andywhite27

Thanks @snicoll