Describe the bug I expanded the functionality of the UsernamePasswordAuthenticationFilter by incorporating a filter that parses a request header containing a JWT token.

A jwtTokenFilter extends the UsernamePasswordAuthenticationFilter and processes the JWT token sent as a header in the HTTP request.

Upon testing, the request is encountering a 403 Forbidden error. During debugging, it was observed that the JWT TokenFiltersuccessfully parses the JWT token, authenticates the user, and sets the SecurityContextHolder with the authentication object. However, when the subsequent filters are executed, the AuthorizationFilter fails to retrieve the authentication from the SecurityContextHolderStrategy. Instead, it consistently sets the SecurityContext to AnonymousAuthenticationToken, resulting in a failure to process the request and leading to a 403 access denied error.

The below error was encountered while migrating the existing authentication utils library to use Spring Security 6.2.x. I've done this in older versions with WebSecurityConfigurerAdapter without any problem but using this way didn't work.

Error Log

2024-01-05T18:26:19.822Z  INFO 82179 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-01-05T18:26:19.822Z  INFO 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-01-05T18:26:19.822Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected StandardServletMultipartResolver
2024-01-05T18:26:19.822Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected AcceptHeaderLocaleResolver
2024-01-05T18:26:19.822Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected FixedThemeResolver
2024-01-05T18:26:19.824Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@37ecc472
2024-01-05T18:26:19.824Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.support.SessionFlashMapManager@768d8a25
2024-01-05T18:26:19.825Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2024-01-05T18:26:19.825Z  INFO 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms
2024-01-05T18:26:19.856Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@6acdca3a, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@32ae890, org.springframework.security.web.context.SecurityContextHolderFilter@3d5009c0, org.springframework.security.web.header.HeaderWriterFilter@22c4151b, org.springframework.security.web.authentication.logout.LogoutFilter@548e70f0, com.demo.authentication.filter.JwtAuthenticationFilter@44384b4a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@45ed58b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7bfd8f92, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@45bb502f, org.springframework.security.web.session.SessionManagementFilter@6f65b61d, org.springframework.security.web.access.ExceptionTranslationFilter@797dd7ef, org.springframework.security.web.access.intercept.AuthorizationFilter@6c80b1d2]] (1/1)
2024-01-05T18:26:19.856Z DEBUG 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /tasks?user=PTS3
2024-01-05T18:26:19.859Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/12)
2024-01-05T18:26:19.864Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/12)
2024-01-05T18:26:19.866Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/12)
2024-01-05T18:26:19.867Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/12)
2024-01-05T18:26:19.868Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (5/12)
2024-01-05T18:26:19.869Z TRACE 82179 --- [nio-8080-exec-1] 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]]
2024-01-05T18:26:19.869Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking JwtAuthenticationFilter (6/12)
2024-01-05T18:26:23.390Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : HTTP GET https://demo.net/services/authentication/publickey/auth-2048
2024-01-05T18:26:23.391Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2024-01-05T18:26:23.605Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Response 200 OK
2024-01-05T18:26:23.606Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Reading to [com.demo.authentication.filter.AuthenticationKey]
2024-01-05T18:26:23.786Z DEBUG 82179 --- [nio-8080-exec-1] c.e.p.a.filter.JwtAuthenticationFilter   : user dummyUser has roles [DEMO_READ]
2024-01-05T18:26:31.571Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking RequestCacheAwareFilter (7/12)
2024-01-05T18:26:31.572Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (8/12)
2024-01-05T18:26:31.575Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (9/12)
2024-01-05T18:26:31.575Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking SessionManagementFilter (10/12)
2024-01-05T18:26:31.576Z TRACE 82179 --- [nio-8080-exec-1] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
2024-01-05T18:26:31.576Z TRACE 82179 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]
2024-01-05T18:26:31.576Z DEBUG 82179 --- [nio-8080-exec-1] o.s.s.w.session.SessionManagementFilter  : Request requested invalid session id 1B6B6644B3B621777DA8773AE8FDCB28
2024-01-05T18:26:31.576Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (11/12)
2024-01-05T18:26:31.576Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking AuthorizationFilter (12/12)
2024-01-05T18:26:33.497Z TRACE 82179 --- [nio-8080-exec-1] estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@2f423264]
2024-01-05T18:26:33.507Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-01-05T18:26:33.509Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-01-05T18:26:33.509Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-01-05T18:26:33.510Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-01-05T18:26:33.511Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-01-05T18:26:33.512Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-01-05T18:26:33.512Z TRACE 82179 --- [nio-8080-exec-1] estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@2f423264] using org.springframework.security.authorization.AuthenticatedAuthorizationManager@6ac7d5f2
2024-01-05T18:26:36.232Z TRACE 82179 --- [nio-8080-exec-1] o.s.s.w.a.ExceptionTranslationFilter     : Sending AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]] to authentication entry point since access is denied

org.springframework.security.access.AccessDeniedException: Access Denied
    at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:98) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at com.demo.authentication.filter.JwtAuthenticationFilter.doFilterInternal(JwtAuthenticationFilter.java:86) ~[demo-util-authentication-filter-4.0.0.jar:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) ~[spring-security-web-6.1.4.jar:6.1.4]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268) ~[spring-web-6.0.12.jar:6.0.12]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.12.jar:6.0.12]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.12.jar:6.0.12]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1740) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.13.jar:10.1.13]
    at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]

2024-01-05T18:26:36.241Z DEBUG 82179 --- [nio-8080-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-01-05T18:26:36.241Z TRACE 82179 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match request to [Is Secure]
2024-01-05T18:26:36.246Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@6acdca3a, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@32ae890, org.springframework.security.web.context.SecurityContextHolderFilter@3d5009c0, org.springframework.security.web.header.HeaderWriterFilter@22c4151b, org.springframework.security.web.authentication.logout.LogoutFilter@548e70f0, com.demo.authentication.filter.JwtAuthenticationFilter@44384b4a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@45ed58b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7bfd8f92, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@45bb502f, org.springframework.security.web.session.SessionManagementFilter@6f65b61d, org.springframework.security.web.access.ExceptionTranslationFilter@797dd7ef, org.springframework.security.web.access.intercept.AuthorizationFilter@6c80b1d2]] (1/1)
2024-01-05T18:26:36.247Z DEBUG 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /error?user=PTS3
2024-01-05T18:26:36.247Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/12)
2024-01-05T18:26:36.247Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/12)
2024-01-05T18:26:36.247Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/12)
2024-01-05T18:26:36.247Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/12)
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (5/12)
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] 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]]
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking JwtAuthenticationFilter (6/12)
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking RequestCacheAwareFilter (7/12)
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (8/12)
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (9/12)
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking SessionManagementFilter (10/12)
2024-01-05T18:26:36.248Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (11/12)
2024-01-05T18:26:36.249Z TRACE 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Invoking AuthorizationFilter (12/12)
2024-01-05T18:26:36.754Z TRACE 82179 --- [nio-8080-exec-1] estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ org.apache.catalina.core.ApplicationHttpRequest@72742c69]]
2024-01-05T18:26:36.758Z DEBUG 82179 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2024-01-05T18:26:36.758Z DEBUG 82179 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2024-01-05T18:26:36.758Z DEBUG 82179 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2024-01-05T18:26:36.759Z DEBUG 82179 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2024-01-05T18:26:36.759Z TRACE 82179 --- [nio-8080-exec-1] estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ org.apache.catalina.core.ApplicationHttpRequest@72742c69]] using org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer$$Lambda$1359/0x0000000131948000@cc4efd1
2024-01-05T18:26:37.221Z DEBUG 82179 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Secured GET /error?user=PTS3
2024-01-05T18:26:37.225Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error?user=PTS3", parameters={masked}
2024-01-05T18:26:37.228Z DEBUG 82179 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2024-01-05T18:26:37.254Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json]
2024-01-05T18:26:37.256Z DEBUG 82179 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [{timestamp=Fri Jan 05 18:26:37 GMT 2024, status=403, error=Forbidden, path=/tasks (truncated)...]
2024-01-05T18:26:37.272Z  INFO 82179 --- [nio-8080-exec-1] i.StatisticalLoggingSessionEventListener : Session Metrics {
    0 nanoseconds spent acquiring 0 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    0 nanoseconds spent preparing 0 JDBC statements;
    0 nanoseconds spent executing 0 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}
2024-01-05T18:26:37.275Z DEBUG 82179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 403
2024-01-05T18:26:37.276Z TRACE 82179 --- [nio-8080-exec-1] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
2024-01-05T18:26:37.276Z TRACE 82179 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]

Code Snippets

*Security Configurer*

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
// @EnableGlobalMethodSecurity(prePostEnabled = true)
public class JwtWebSecurityConfigurerAdaptor {

  @Autowired
  private AuthenticationConfiguration authenticationConfiguration;

  @Value("${authentication.service.url}")
  private String authenticationServiceUrl;

  @Value("${allowed.clock.skew:0}")
  private long allowedClockSkew;

  /**
   * Standard RestTemplate - this is used by the key resolver to obtain public keys.
   * 
   * @return
   */
  @Bean(name="keyResolverRestTemplate")
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

  @Bean
  public JwtPublicKeyResolver jwtPublicKeyResolver() {
    return new JwtPublicKeyResolver(restTemplate(), authenticationServiceUrl);
  }

  @Bean
  public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
    JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager(), jwtPublicKeyResolver(), allowedClockSkew);
    jwtAuthenticationFilter.setSecurityContextRepository(new DelegatingSecurityContextRepository(new RequestAttributeSecurityContextRepository(), new HttpSessionSecurityContextRepository()));
    return jwtAuthenticationFilter;
  }

  @Bean
  public SecurityFilterChain securityFilterChain(final HttpSecurity http) throws Exception {
    http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(requests -> requests
            .requestMatchers("/info").permitAll()
            .requestMatchers("/health").permitAll()
            .requestMatchers("/actuator/**").permitAll()
            .requestMatchers("/swagger-ui.html").permitAll()
            // .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
            .requestMatchers("/swagger-ui/**").permitAll()
            .requestMatchers("/v3/api-docs/**").permitAll()
            .anyRequest().authenticated()
        );
    http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
    http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    return http.build();
  }

  @Bean
  public AuthenticationManager authenticationManager() throws Exception {
    return authenticationConfiguration.getAuthenticationManager();
  }
}

*JwtFilter*

public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

  private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

  private static final String AUTHORIZATION_HEADER = "Authorization";

  private static final String BEARER = "Bearer ";

  private long allowedClockSkew;

  private JwtPublicKeyResolver publicKeyResolver;

  private AuthenticationManager authenticationManager;

  public JwtAuthenticationFilter(
      final AuthenticationManager authenticationManager, final JwtPublicKeyResolver publicKeyResolver, long allowedClockSkew) {
    super(authenticationManager);
    this.authenticationManager = authenticationManager;
    this.publicKeyResolver = publicKeyResolver;
    this.allowedClockSkew = allowedClockSkew;
  }

  @Override
  protected void doFilterInternal(final HttpServletRequest httpServletRequest,
      final HttpServletResponse httpServletResponse, final FilterChain filterChain)
      throws IOException, ServletException {

    try {

      // Get the jwt token out of the header
      final String authenticationHeader = httpServletRequest.getHeader(AUTHORIZATION_HEADER);

      if (authenticationHeader != null && authenticationHeader.startsWith(BEARER)) {

        final String authenticationToken = authenticationHeader.substring(BEARER.length());

        try {

          // Validate the jwt
          final Jws<Claims> jws = Jwts.parserBuilder().setSigningKeyResolver(publicKeyResolver)
              .setAllowedClockSkewSeconds(allowedClockSkew).build()
              .parseClaimsJws(authenticationToken);

          configureSecurityContextFromClaims(authenticationToken, jws, httpServletRequest);
          configureFeatureToggleContextFromClaims(jws);

        } catch (JwtException ex) {
          LOGGER.warn("Invalid JWT token", ex);
          httpServletResponse.sendError(HttpStatus.UNAUTHORIZED.value(),
              "Invalid JWT Token: " + ex.getLocalizedMessage());
          return;
        }
      }
      filterChain.doFilter(httpServletRequest, httpServletResponse);

    } finally {
      // clear the feature toggle context for use in the next request / thread
      FeatureToggleContextHolder.getContext().reset();
    }
  }

  @SuppressWarnings("unchecked")
  private void configureFeatureToggleContextFromClaims(Jws<Claims> jws) {
    List<String> featureToggles = jws.getBody().get("featureToggles", ArrayList.class);
    if (featureToggles == null) {
      featureToggles = Collections.emptyList();
    }
    FeatureToggleContextHolder.getContext().setActiveFeatureToggles(featureToggles);
  }

  @SuppressWarnings("unchecked")
  private void configureSecurityContextFromClaims(String authenticationToken, Jws<Claims> jws, HttpServletRequest httpServletRequest) {
    final String user = jws.getBody().getSubject();
    final List<String> roles = jws.getBody().get("roles", ArrayList.class);

    final List<GrantedAuthority> authorities =
        roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug(String.format("user %s has roles %s and grantedAuthorities %s",
          user, roles.toString(), authorities.toString()));
    }
    // Create the authentication object for use in the controllers and set the security context
    UsernamePasswordAuthenticationToken authentication =
        new JWTRelayAuthenticationToken(user, null, authorities, authenticationToken);
    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
    // Authentication authResult = authenticationManager.authenticate(authentication);
    SecurityContextHolder.getContext().setAuthentication(authentication);

  }
}

*Custom UsernamePasswordAuthenticationToken *

public class JWTRelayAuthenticationToken extends UsernamePasswordAuthenticationToken {

  private static final long serialVersionUID = -4874016061387450643L;

  /**
   * JWT token captured from incoming request.
   */
  private String jwtToken = "";

  public JWTRelayAuthenticationToken(Object principal, Object credentials, String jwtToken) {
    super(principal, credentials);
    this.jwtToken = jwtToken;
  }

  public JWTRelayAuthenticationToken(Object principal, Object credentials,
      Collection<? extends GrantedAuthority> authorities, String jwtToken) {
    super(principal, credentials, authorities);
    this.jwtToken = jwtToken;
  }

  public String getJwtToken() {
    return this.jwtToken;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = super.hashCode();
    result = prime * result + ((jwtToken == null) ? 0 : jwtToken.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!super.equals(obj)) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    JWTRelayAuthenticationToken other = (JWTRelayAuthenticationToken) obj;
    if (jwtToken == null) {
      if (other.jwtToken != null) {
        return false;
      }
    } else if (!jwtToken.equals(other.jwtToken)) {
      return false;
    }
    return true;
  }
}

*pom.xml (only dependencies view)*

4.0.0

17 17

io.jsonwebtoken jjwt-api 0.11.5 io.jsonwebtoken jjwt-impl 0.11.5 io.jsonwebtoken jjwt-jackson 0.11.5 com.fasterxml.jackson.core jackson-databind com.fasterxml.jackson.core jackson-databind 2.15.3 javax.xml.bind jaxb-api 2.3.1 runtime commons-io commons-io 2.15.1 org.springframework.security spring-security-config 6.2.1 org.springframework.security spring-security-web 6.2.1 org.slf4j slf4j-api 2.0.9 org.projectlombok lombok 1.18.30 provided jakarta.servlet jakarta.servlet-api 6.0.0 provided

<!-- Test -->
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.3.18</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>3.3.3</version>
  <scope>test</scope>
</dependency>

Please Note *Spring versions when working fine*

  • Spring Security - 4.2.4.RELEASE
  • Spring Boot - 2.7.x

*Spring versions when stopped working as expected*

  • Spring Security - 6.2.1
  • Spring Boot - 3.1.4

Comment From: siukei-au

I have the similar issue and don't know if both issue is related.

I am setting up Spring boot 3.1.4 with Spring Security 6.2.1 in my project. The application keeps sending response code 403 after authentication and I found that the issue will only happened if I defined authorizeHttpRequests in SecurityFilterChain in the Security Config. The application will resume normal after I commented the authorizeHttpRequests like below.

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity, @Autowired AuthenticationManager authenticationManager) throws Exception {
        return httpSecurity
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable)
                .sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authenticationManager(authenticationManager)
                .formLogin(AbstractHttpConfigurer::disable)
                .httpBasic(AbstractHttpConfigurer::disable)
                .logout(LogoutConfigurer::disable)
                .anonymous(AnonymousConfigurer::disable)
//                .authorizeHttpRequests(auths -> auths
//                        .requestMatchers("/products/**").permitAll()
//                        .anyRequest().authenticated()
//                )
                .build();
    }

Also, I found that the custom authentication filter will not register automatically if I add authorizeHttpRequests to SecurityFilterChain. I will need to add the filter manually by addFilterBefore to make sure the filter added to the filter chain.

However, the filter will be executed twice in 1 request after added the filter manually. Even if I remove the @Component annotation to ensure spring will not inject automatically the filter still run 2 time in a row.

Log file showing the filter processed two time:

2024-01-11T10:31:28.898+08:00  INFO 39620 --- [customer-profile-management] [nio-8081-exec-1] c.j.security.filter.ApiKeyAuthFilter     : Authentication Successfully
2024-01-11T10:31:28.899+08:00  INFO 39620 --- [customer-profile-management] [nio-8081-exec-1] c.j.security.filter.ApiKeyAuthFilter     : Authentication Successfully

P.S. this is my first time setting up the spring security project, I am not very familiar with it and don't know if it's a mis-config in my side or what.

Comment From: mikebgrep

Rather open a new issue, I will provide a simple reproduction project here as I have similar problem to this issue. After I migrate from Spring boot 2.8.7 to Spring Boot 3.2.1 with Spring Security 6 when the Security configuration is with anyRequest().authenticated() I receive 403 Forbidden if i permitAll() requests, everything work as generating JWT and using the application.

Securing POST /accounts 2024-01-13T16:18:04.537+02:00 DEBUG 73343 --- [nio-8082-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-01-13T16:18:04.539+02:00 DEBUG 73343 --- [nio-8082-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint : Pre-authenticated entry point called. Rejecting access 2024-01-13T16:18:04.546+02:00 DEBUG 73343 --- [nio-8082-exec-1] o.s.security.web.FilterChainProxy : Securing POST /error 2024-01-13T16:18:04.547+02:00 DEBUG 73343 --- [nio-8082-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-01-13T16:18:04.547+02:00 DEBUG 73343 --- [nio-8082-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint : Pre-authenticated entry point called. Rejecting access You can take a look the simple project its use H2 as databse. Reproduction repository link: https://github.com/mikebgrep/simple-spring-security-reporoduction

Comment From: kse-music

see gh-14450 comment

Comment From: marcusdacoregio

I provided some feedback on https://github.com/spring-projects/spring-security/issues/14450#issuecomment-1896309341

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

Comment From: afsarkhan05

I am still seeing this issue with spring boot starter 3.2.3 version

Comment From: medaminefracso

@afsarkhan05 I still have this issue with the same spring boot version you mentioned. Did you manage to solve it ?

Comment From: afsarkhan05

@medaminefracso , I fixed the issue, it was related , the way I was using Auth Filter in my code, You can take a look at the working code here

https://github.com/afsarkhan05/ecommerce-app/tree/feature-S1E5-optimize-pom

Comment From: NathanJAdams

@afsarkhan05 How did you solve it? I've looked at your code and can't see what changed that fixed the issue

Comment From: medaminefracso

@NathanJAdams I resolved the issue by fixing a bug within a service. The bug stemmed from an exception that occurred due to an incorrect database query. Once I solved this issue, 403 FORBIDDEN was no longer returned.

It's a bit weird.. But this resolved this issue in my case.

Feel free to reach out if I can help.

Comment From: afsarkhan05

@NathanJAdams it's hard for me to recall what fixed the issue, But i remember I had @Bean (in service configuration file) and @Component on Filter itself to Auth Filter(Seems, it was dubious to have both together)

I made 2 changes, removed @Bean from service configuration for Auth Filter and put the scan package in main java for Auth Filter package as it was different package structure than service package.

Hope this may help you.

Comment From: NathanJAdams

Thank you both @medaminefracso @afsarkhan05 :pray:

For my app there were two options that "fixed it", or to be more precise, stopped it erroring:

  1. Disable CSRF by adding a httpSecurity.csrf(AbstractHttpConfigurer::disable) call when creating the SecurityFilterChain bean
  2. Add CSRF tokens to requests in tests eg. MockMvcRequestBuilders.post("/endpoint").with(csrf())

Comment From: harekrishna21

@NathanJAdams I resolved the issue by fixing a bug within a service. The bug stemmed from an exception that occurred due to an incorrect database query. Once I solved this issue, 403 FORBIDDEN was no longer returned.

It's a bit weird.. But this resolved this issue in my case.

Feel free to reach out if I can help.

Comment From: harekrishna21

Hi How you resolved this Can you suggest me, actually facing the same in spring6.x.