Using Spring 6.0.2 and Spring-Security 6.0.0. No spring-boot involved.
Describe the bug
Following deprecation notice on authorizeRequests() to replace with authorizeHttpRequests() results in broken configuration.
To Reproduce
Configure a filter chain, using the deprecated authorizeRequests() method, as per: https://github.com/au-research/raido-v2/blob/f0b5de3e1c60fcf9450030564263f1bb0c682080/api-svc/spring/src/main/java/raido/apisvc/spring/config/RaidWebSecurityConfig.java#L79
Then try to implement the deprecation notice by replacing with authorizeHttpRequests(), suddenly endpoints marked with fullyAuthenticated() result in 403 errors.
Expected behavior
FilterChain should secure the system as it did before, or documentation should be added to describe the new functionality (preferably, with a description of how to obtain the previous behaviour).
Work-around
Keep using deprecated authorizeRequests() for the foreseeable future.
Analysis
Some analysis done on this StackOverflow question: https://stackoverflow.com/questions/74568979/spring-security-6-replacing-deprecated-authorizerequests-results-in-provider
Reproduced here:
It seems this happens because my AuthenticationProvider instances aren't being called, because the ProviderManager isn't being called. Since the AuthnProviders don't get called, the security context still contains the pre-auth token instead of a verified post-auth token, so the eventual call to AuthorizationStrategy.isGranted() ends up calling isAuthenticated() on the pre-auth token, which (correctly) returns false and the request is denied.
In the comments to that question, it was pointed out:
I see no other filter capable of performing authentication it is expected that your AuthenticationManager won't be called.
My assumption about why this works with authorizeRequests() was just that the Spring-Security @EnableWebSecurity annotation mechanism was supposed to do the work to integrate the created SecurityFilterChain into the Spring @EnableWebMvc mechanism.
This implementation still seems to work, as long as you use the deprecated authorizeRequests() method when creating the filter chain. But, given that implementing the deprecation notice breaks the config: maybe that's a bad assumption on my part, or maybe it's a bug with the implementation or documentation (hence this issue).
When using authorizeRequests(), spring-security seems to:
1. Invoke the FilterChain's SecurityContextRepo to set the SecurityContext to a pre-auth token
2. Invoke all of the FilterChain's AutheticationProvider implementations to replace the SecurityContext pre-auth token with a post-auth token.
3. Apply authorisation logic to the request depending on config
After replacing with authorizeHttpRequests(), step 2 doesn't happen.
Comment From: marcusdacoregio
Hi @ardc-shorn, thanks for the report.
Can you share what your request looks like? What type of authentication are you using, basic or form?
Comment From: ardc-shorn
@marcusdacoregio They're REST API calls, authenticated via a bearer token.
Comment From: marcusdacoregio
I have answered in the Stackoverflow question https://stackoverflow.com/questions/74568979/spring-security-6-403-denied-because-authenticationprovider-not-called/74613656#74613656