Why am I getting random AuthenticationCredentialsNotFoundException with an authenticated user?

81 Views Asked by At

I am using spring security with oauth2 to authenticate users on my website, most of the time everything work fine but from time to time requests returns 401 error code with this stacktrace:

TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Ant [pattern='/**', OPTIONS], Filters=[]] (1/4)
TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Or [Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']], Filters=[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2227c82d, org.springframework.security.web.context.SecurityContextPersistenceFilter@1eedf268, org.springframework.security.web.header.HeaderWriterFilter@414b5798, org.springframework.security.web.authentication.logout.LogoutFilter@7d727123, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@52688730, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6d9069ab, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@69abff1d, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1b9075c9, org.springframework.security.web.session.SessionManagementFilter@5ffae42f, org.springframework.security.web.access.ExceptionTranslationFilter@6b8cfbeb, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@6ab56a77]] (2/4)
TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration$NotOAuthRequestMatcher@37905236, Filters=[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4fdb338e, org.springframework.security.web.context.SecurityContextPersistenceFilter@11a88d87, org.springframework.security.web.header.HeaderWriterFilter@6364d449, org.springframework.security.web.authentication.logout.LogoutFilter@4c14ed24, org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter@25dc8147, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@ce24a98, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@496101d1, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2de22e7, org.springframework.security.web.session.SessionManagementFilter@fabe3f8, org.springframework.security.web.access.ExceptionTranslationFilter@2b46d238, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@158774d3]] (3/4)
DEBUG o.s.security.web.FilterChainProxy - Securing GET /services/notifications/getAllNotifications?gencodDeclarant=3025598727402
TRACE o.s.security.web.FilterChainProxy - Invoking WebAsyncManagerIntegrationFilter (1/11)
TRACE o.s.security.web.FilterChainProxy - Invoking SecurityContextPersistenceFilter (2/11)
DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - Set SecurityContextHolder to empty SecurityContext
TRACE o.s.security.web.FilterChainProxy - Invoking HeaderWriterFilter (3/11)
TRACE o.s.security.web.FilterChainProxy - Invoking LogoutFilter (4/11)
TRACE o.s.s.w.a.logout.LogoutFilter - Did not match request to Or [Ant [pattern='/logout', GET], Ant [pattern='/logout', POST], Ant [pattern='/logout', PUT], Ant [pattern='/logout', DELETE]]
TRACE o.s.security.web.FilterChainProxy - Invoking OAuth2AuthenticationProcessingFilter (5/11)
DEBUG o.s.s.o.p.a.OAuth2AuthenticationProcessingFilter - Authentication success: OAuth2Authentication [Principal=3025598727402, Credentials=[PROTECTED], Authenticated=true, Details=remoteAddress=127.0.0.1, tokenType=BearertokenValue=<TOKEN>, Granted Authorities=[FOURNISSEUR]]
TRACE o.s.security.web.FilterChainProxy - Invoking RequestCacheAwareFilter (6/11)
TRACE o.s.security.web.FilterChainProxy - Invoking SecurityContextHolderAwareRequestFilter (7/11)
TRACE o.s.security.web.FilterChainProxy - Invoking AnonymousAuthenticationFilter (8/11)
TRACE o.s.s.w.a.AnonymousAuthenticationFilter - Did not set SecurityContextHolder since already authenticated OAuth2Authentication [Principal=3025598727402, Credentials=[PROTECTED], Authenticated=true, Details=remoteAddress=127.0.0.1, tokenType=BearertokenValue=<TOKEN>, Granted Authorities=[FOURNISSEUR]]
TRACE o.s.security.web.FilterChainProxy - Invoking SessionManagementFilter (9/11)
TRACE o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Preparing session with ChangeSessionIdAuthenticationStrategy (1/1)
TRACE o.s.security.web.FilterChainProxy - Invoking ExceptionTranslationFilter (10/11)
TRACE o.s.security.web.FilterChainProxy - Invoking FilterSecurityInterceptor (11/11)
TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='/actuator/**', OPTIONS] - [#oauth2.throwOnError(permitAll)] (1/7)
TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='/api-docs/**', OPTIONS] - [#oauth2.throwOnError(permitAll)] (2/7)
TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='api/v2/api-docs', OPTIONS] - [#oauth2.throwOnError(permitAll)] (3/7)
TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='/swagger-ui.html', OPTIONS] - [#oauth2.throwOnError(permitAll)] (4/7)
TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='/pdf**', OPTIONS] - [#oauth2.throwOnError(permitAll)] (5/7)
TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='/services/**/public/**'] - [#oauth2.throwOnError(permitAll)] (6/7)
TRACE o.s.s.w.a.i.FilterSecurityInterceptor - Did not re-authenticate OAuth2Authentication [Principal=3025598727402, Credentials=[PROTECTED], Authenticated=true, Details=remoteAddress=127.0.0.1, tokenType=BearertokenValue=<TOKEN>, Granted Authorities=[FOURNISSEUR]] before authorizing
TRACE o.s.s.w.a.i.FilterSecurityInterceptor - Authorizing filter invocation [GET /services/notifications/getAllNotifications?gencodDeclarant=3025598727402] with attributes [#oauth2.throwOnError(authenticated)]
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorized filter invocation [GET /services/notifications/getAllNotifications?gencodDeclarant=3025598727402] with attributes [#oauth2.throwOnError(authenticated)]
TRACE o.s.s.w.a.i.FilterSecurityInterceptor - Did not switch RunAs authentication since RunAsManager returned null
DEBUG o.s.security.web.FilterChainProxy - Secured GET /services/notifications/getAllNotifications?gencodDeclarant=3025598727402
TRACE o.s.s.w.a.ExceptionTranslationFilter - Sending to authentication entry point since authentication failed
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:333)
...

From the logs the user is clearly recognized but spring security doesn't seem to find it in the context. It happens randomly and on different endpoints so its hard for me to find the source of the problem.

All my endpoints are annotated with @PreAuthorize to only allow some parameter values when an authenticated user is calling the endpoint.

    @GetMapping(value = "/getAllNotifications")
    @PreAuthorize("@authorizationService.isGlnEqual(#gencodDeclarant, authentication.name)")
    public NotificationDto getAllNotifications(@RequestParam("gencodDeclarant") String gencodDeclarant) {
        return notificationService.getAllNotifications(gencodDeclarant);
    }

Some context: I'm using spring-boot v2.5.7, spring-security-oauth2 v2.3.3.RELEASE, spring-security-jwt v1.0.7.RELEASE

My @EnableResourceServer and GlobalMethodSecurity configuration:

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf()
            .disable()
            .requestMatchers()
            .and()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/services/**/public/**")
            .permitAll()
            .antMatchers("/services/**")
            .authenticated();
    }
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return getOAuth2MethodSecurityExpressionHandler();
    }

    @Bean
    public OAuth2MethodSecurityExpressionHandler getOAuth2MethodSecurityExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

Since the user calling the endpoint is authenticated, as we can see in the logs, I was expecting the resource to be returned yet sometimes it is not the case.

0

There are 0 best solutions below