I am upgrading from Spring 2.7.10 to 3.1. Part of that is converting authorizeRequests to authorizeHttpRequests.
I'm using the example here as a guideline: https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html#favor-permitall
My old code looked like so and still works in v3.1 but throws deprecation warnings:
http.authorizeRequests().requestMatchers("/authenticate/**").permitAll().anyRequest().authenticated();
When I modify it to get rid of the deprecation warnings it no longer works:
http.authorizeHttpRequests((authorize) -> authorize.requestMatchers("/authenticate/**").permitAll().anyRequest().authenticated());
Note that all other config code is identical. The only difference is the one line above to remove the deprecation warning.
Am I doing something wrong or is this a bug? I am calling a url similar to https://someserver/authenticate/blah from a frontend service. FWIW if I call it directly in the browser I notice I do get different HTTP responses for both. i.e. A direct call with authorizeHttpRequests generates a 403 code whereas authorizeRequests generates a 405 code.
Comment From: marcusdacoregio
Hi @UglyHobbitFeet, thanks for the report.
Can you share more details about your request? Are you sending any kind of authentication with it, even if it permits all? Ideally, it would be great if you can provide a minimal, reproducible sample, if not, please try to share as much detail as possible.
A direct call with authorizeHttpRequests generates a 403 code whereas authorizeRequests generates a 405 code.
This is odd, 405 means that the HTTP method is not supported. Can you also add the code of the controller that handles that method?
Comment From: UglyHobbitFeet
I am sending X509 authentication that extends ( org.springframework.security.authentication.AbstractAuthenticationToken) along with the request. Unfortunately I cannot share that code nor do I have a small reproducible sample.
On Tue, Jun 13, 2023 at 8:07 AM Marcus Hert Da Coregio ***@***.*** wrote:
Hi @UglyHobbitFeet https://github.com/UglyHobbitFeet, thanks for the report.
Can you share more details about your request? Are you sending any kind of authentication with it, even if it permits all? Ideally, it would be great if you can provide a minimal, reproducible sample, if not, please try to share as much detail as possible.
A direct call with authorizeHttpRequests generates a 403 code whereas authorizeRequests generates a 405 code.
This is odd, 405 means that the HTTP method is not supported. Can you also add the code of the controller that handles that method?
— Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-security/issues/13303#issuecomment-1589174790, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALBDS7WQJKFLIK2ABKFOMKTXLBJXXANCNFSM6AAAAAAZA62JM4 . You are receiving this because you were mentioned.Message ID: @.***>
Comment From: marcusdacoregio
In that case, I would recommend adding logging.level.org.springframework.security=TRACE to your application.properties and checking the console logs. The difference between authorizeRequests(...) (FilterSecurityInterceptor) and authorizeHttpRequests(...) (AuthorizationFilter) is that the former tries to authenticate the user if possible, that might be one of the reasons. Maybe your request is falling into the anyRequest, the filter authenticates it and the request is allowed, but we need some debugging to be sure. You can try putting a breaking-point in both of those filter to see what is happening exactly.
You do not need to share the details as is, you can mask them and just share the pertinent parts.
Comment From: UglyHobbitFeet
- I changed to username/password login and it works fine. So It is definitely tied to the X509 portion.
- I did as you suggested and the output for X509 is shown below
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@6238d5e0, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@336f49a1, org.springframework.security.web.context.SecurityContextHolderFilter@7ea42c82, org.springframework.security.web.header.HeaderWriterFilter@2c9fdb64, org.springframework.security.web.authentication.logout.LogoutFilter@3e43f049, MyCustomX509Filter@31464a43, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@ceb7701, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5e193ef5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2c8b8de0, org.springframework.security.web.session.SessionManagementFilter@1c3b6963, org.springframework.security.web.access.ExceptionTranslationFilter@624b3544, org.springframework.security.web.access.intercept.AuthorizationFilter@61b60600]] (1/1)
DEBUG 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Securing POST /myEndpoint
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking DisableEncodeUrlFilter (1/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking WebAsyncManagerIntegrationFilter (2/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderFilter (3/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking HeaderWriterFilter (4/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (5/12)
TRACE 1 --- [-nio-443-exec-9] 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 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking MyCustomX509Filter (6/12)
TRACE 1 --- [-nio-443-exec-9] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking RequestCacheAwareFilter (7/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderAwareRequestFilter (8/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking AnonymousAuthenticationFilter (9/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking SessionManagementFilter (10/12)
TRACE 1 --- [-nio-443-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter : Did not set SecurityContextHolder since already authenticated MyCustomX509Token [Principal=MyPrincipalInfo, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]
TRACE 1 --- [-nio-443-exec-9] s.CompositeSessionAuthenticationStrategy : Preparing session with ChangeSessionIdAuthenticationStrategy (1/1)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking ExceptionTranslationFilter (11/12)
TRACE 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Invoking AuthorizationFilter (12/12)
TRACE 1 --- [-nio-443-exec-9] estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@1d3a4d5b]
TRACE 1 --- [-nio-443-exec-9] estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@1d3a4d5b] using org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer$$Lambda$1151/0x0000000801403198@9a79ef4
DEBUG 1 --- [-nio-443-exec-9] o.s.security.web.FilterChainProxy : Secured POST /myEndpoint
Comment From: marcusdacoregio
The x509 part of your code seems to be customized, so there is not much we can assume from here. It is important to remember that permitAll will try to authenticate the user if possible, contrary to WebSecurity#ignoring which does not invoke the filters.
I changed to username/password login and it works fine.
What is working fine? Which request? What clues did you get from making that change?
Comment From: UglyHobbitFeet
I am not sure what other logging I can provide. I know the X509 code works with the deprecated authroizeRequests call
My application has two modes of authentication. One is X509, the other is username/password. Based off your comments I decided to switch to username/password to see if it worked, and it did. So I thought I would mention that in my response because it helped confirm that the X509 is what is tripping up the authorizeHttpRequests call.
Comment From: marcusdacoregio
I am sorry but I still do not understand what you mean by working/not working. You mentioned:
My old code looked like so and still works in v3.1 but throws deprecation warnings:
and
When I modify it to get rid of the deprecation warnings it no longer works:
But you haven't explained what happens when it's working and vice-versa. Your configuration permitted all on /authenticate/** and on the other comment you provided a request hitting /myEndpoint, which made me confused.
Comment From: UglyHobbitFeet
Regarding the first comment. By 'Working" I mean I am allowed to hit the endpoint and get back expected results. By "Not Working" I mean I am not getting back expected results.
Regarding the second comment, it should be /'authenticate'. I just manually edited the log files to say '/myEndpoint' when I was cleaning them up for posting in this issue. My apologies for causing confusion on this due to cleaning up log file output.
Comment From: marcusdacoregio
It is strange that you have an authentication token in the security context with no authorities:
TRACE 1 --- [-nio-443-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter : Did not set SecurityContextHolder since already authenticated MyCustomX509Token [Principal=MyPrincipalInfo, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]
However, your logs do not show the 403 happening. If there is any security-related error, the exception should be printed to the console. Can you find it in the logs output?
Comment From: UglyHobbitFeet
I went through the code and created a cleaned up version of what I'm doing. I hope this helps to make sense of why it's failing.
Comment From: marcusdacoregio
Hi @UglyHobbitFeet, since you did not share the logs where the 403 is happening, and based on what I could assume from your code, here are my thoughts:
- The code on
CustomX509AuthenticationProcessingFilter#attemptAuthenticationlooks strange, ideally it should run the authentication token against anAuthenticationManager, see theUsernamePasswordAuthenticationFilterimplementation as an example. - The token returned from
CustomX509AuthenticationProcessingFilter#attemptAuthenticationis not authenticated, therefore, when usingauthorizeRequests(...)and the code hits this method, that unauthenticated token gets authenticated using theCustomX509AuthenticationProvider. However, when you switch toauthorizeHttpRequestsyou are switching fromFilterSecurityInterceptortoAuthorizationFilter, and the latter does not re-authenticate the request.
With that said I suggest that you put a breakpoint on the code I linked above to check the behavior described and you should revisit your custom filter implementation in order to validate the authentication token against the AuthenticationManager that you already have, that should get things working for you.
Comment From: UglyHobbitFeet
@marcusdacoregio You nailed it, thanks! I made the edits you mentioned in your latest post and it started working with the authorizeHttpRequests. Thanks again for all your help!