Skip to content

permitAll() broken? #13303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
UglyHobbitFeet opened this issue Jun 9, 2023 · 12 comments
Closed

permitAll() broken? #13303

UglyHobbitFeet opened this issue Jun 9, 2023 · 12 comments
Assignees
Labels
in: web An issue in web modules (web, webmvc) status: invalid An issue that we don't feel is valid

Comments

@UglyHobbitFeet
Copy link

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.

@UglyHobbitFeet UglyHobbitFeet added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Jun 9, 2023
@jzheaux jzheaux added in: web An issue in web modules (web, webmvc) and removed status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Jun 12, 2023
@marcusdacoregio
Copy link
Contributor

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?

@marcusdacoregio marcusdacoregio added the status: waiting-for-feedback We need additional information before we can continue label Jun 13, 2023
@UglyHobbitFeet
Copy link
Author

UglyHobbitFeet commented Jun 13, 2023 via email

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jun 13, 2023
@marcusdacoregio
Copy link
Contributor

marcusdacoregio commented Jun 13, 2023

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.

@marcusdacoregio marcusdacoregio added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Jun 13, 2023
@UglyHobbitFeet
Copy link
Author

  1. I changed to username/password login and it works fine. So It is definitely tied to the X509 portion.
  2. 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

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jun 13, 2023
@marcusdacoregio
Copy link
Contributor

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?

@UglyHobbitFeet
Copy link
Author

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.

@marcusdacoregio
Copy link
Contributor

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.

@UglyHobbitFeet
Copy link
Author

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.

@marcusdacoregio
Copy link
Contributor

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?

@UglyHobbitFeet
Copy link
Author

example.txt

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.

@marcusdacoregio
Copy link
Contributor

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:

  1. The code on CustomX509AuthenticationProcessingFilter#attemptAuthentication looks strange, ideally it should run the authentication token against an AuthenticationManager, see the UsernamePasswordAuthenticationFilter implementation as an example.
  2. The token returned from CustomX509AuthenticationProcessingFilter#attemptAuthentication is not authenticated, therefore, when using authorizeRequests(...) and the code hits this method, that unauthenticated token gets authenticated using the CustomX509AuthenticationProvider. However, when you switch to authorizeHttpRequests you are switching from FilterSecurityInterceptor to AuthorizationFilter, 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.

@marcusdacoregio marcusdacoregio added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Jun 15, 2023
@UglyHobbitFeet
Copy link
Author

UglyHobbitFeet commented Jun 16, 2023

@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!

@marcusdacoregio marcusdacoregio added status: invalid An issue that we don't feel is valid and removed status: waiting-for-feedback We need additional information before we can continue labels Jun 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web An issue in web modules (web, webmvc) status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

4 participants