添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
玩篮球的松树  ·  [WARNING] JAR will be ...·  3 周前    · 
帅气的生姜  ·  Excel ...·  7 月前    · 

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 Unexpected behavior when adding a custom authentication filter in place of UsernamePasswordAuthenticationFilter. #12636 Unexpected behavior when adding a custom authentication filter in place of UsernamePasswordAuthenticationFilter. #12636 yousefbinali opened this issue Feb 7, 2023 · 16 comments

Describe the bug
I extended the UsernamePasswordAuthenticationFilter with a filter that parses a JSON payload that contains the username and password.

And added the filter at UsernamePasswordAuthenticationFilter using a custom dsl

It is added in the log below
2023-02-07T09:41:16.941+03:00 INFO 6192 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@4f0cab0a, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@fe7b6b0, org.springframework.security.web.context.SecurityContextHolderFilter@4c86da0c, org.springframework.security.web.header.HeaderWriterFilter@7d0d91a1, org.springframework.security.web.authentication.logout.LogoutFilter@655a01d8, com.example.jsonpayloadauth.JsonUsernamePasswordAuthenticationFilter@7ab4ae59, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6732726, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4190bc8a, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@77681ce4, org.springframework.security.web.access.ExceptionTranslationFilter@1dbd580, org.springframework.security.web.access.intercept.AuthorizationFilter@196ae579]

All the configuration is working so far and when I send a request to /login I get 404 which means the user was authenticated since I don't have any endpoint at / . The issue comes after the authentication when requesting any protected resource. For example, sending a request to /hello-auth respond with

"timestamp": "2023-02-07T06:42:36.466+00:00", "status": 403, "error": "Forbidden", "path": "/hello-auth"

When debugging my custom filter I found out that the user was authenticated. But it seems the user authentication is reset to anonymousUser after finishing the request to /login .

To Reproduce
Add a custom authentication filter at UsernamePasswordAuthenticationFilter

Expected behavior
Implementing a custom authentication filter should work.

Sample

reproducible sample .

Yes, we don't upgrade Spring Security on production becasuse it's unstable and buggy.
Spring made a decision to boot a security and now everybody have to use old stable versions. Meanwhile manuals on https://spring.io covers only very basic not real life cases.
It looks like they benefit hackers job making it easy.

Hi @yousefbinali , I have a few questions based on the provided sample:

  • How do you expect the user to be authenticated? There is no AuthenticationProvider or UserDetailsService . When you call this.getAuthenticationManager().authenticate(authRequest); there is only the AnonymousAuthenticationProvider in place.
  • Since you are using a custom filter, you have to also set its properties. The reason that the authentication is not being saved between requests is that the SecurityContextRepository that's being used is the RequestAttributeSecurityContextRepository (see here ). The defaults have been changed in Spring Security 6 as explained here , but since you are not using the DSL, you have to change the repository yourself, like so:
  • // ...
    JsonUsernamePasswordAuthenticationFilter filter = new JsonUsernamePasswordAuthenticationFilter(authenticationManager);
    filter.setSecurityContextRepository(new DelegatingSecurityContextRepository(
    				new RequestAttributeSecurityContextRepository(),
    				new HttpSessionSecurityContextRepository()
    http.addFilterAt(filter, UsernamePasswordAuthenticationFilter.class);
    // ...

    Please try the above suggestions and see if it works.

    Hi @marcusdacoregio ,

    Answering your question, I'm using the default In-memory authentication configuration which means DaoAuthenticationProvider and InMemoryUserDetailsManager . The AuthenticationManager returned by this.getAuthenticationManager() has a parent that has DaoAuthenticationProvider in providers list. I don't know how things are configured but I figured this when I was debugging.

    Your solution has worked perfectly! I totally missed out the new default SecurityContextRepository .
    Thank you so much for you help.

    @marcusdacoregio thank you for your reply! I see that Spring Security Team doing their best but I'm working with Spring for 6 years continuously and there never been situation like this, when documentation didn't help.
    I have an issue:
    Spring security always gives 403 when SecurytyFilterChain is used with Keycloak v20.0.3 authorization server.
    Without SecurytyFilterChain authorization works totally fine, requires only adding two lines to spring config:

    spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/myrealm
    spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/realms/myrealm/protocol/openid-connect/certs
    

    Adding simple SecurityChain even basic one from Spring guides (see code below) always gives 403 on any request (get/post) - no matter if token is correct or not, no matter path:

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
      http.cors().and()
        .authorizeHttpRequests((requests) -> requests
        .requestMatchers("/").permitAll()
        .anyRequest().authenticated());
      return http.build();
    

    It could be easily reproduced:

  • Setup Keycloack;
  • Setup Spring to use Keycloack by adding in application.properties:
  • spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/myrealm
    spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/realms/myrealm/protocol/openid-connect/certs
    
  • Make sure authorization works fine.
  • Add WebSecurityConfig with the following SecurityFilterChain:
  • @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
      http.cors().and()
        .authorizeHttpRequests((requests) -> requests
        .requestMatchers("/").permitAll()
        .anyRequest().authenticated());
      return http.build();
    

    Expected behavior:
    Not getting 403 error on all paths/requests.

    @Moberaptor, have you tried adding logging.level.org.springframework.security=TRACE to your application.properties and checking where the 403 is coming from?

    You are setting the resource server properties but it is not enabled in the DSL, you should do http.oauth2ResourceServer(Customizer.withDefaults()).

    Where does your request come from? What does your request look like?

  • Security log is the following:
  • Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@24482a4f, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3140ad41, org.springframework.security.web.context.SecurityContextHolderFilter@790f4933, org.springframework.security.web.header.HeaderWriterFilter@2526d5f9, org.springframework.web.filter.CorsFilter@2e09c51, org.springframework.security.web.csrf.CsrfFilter@463a1f47, org.springframework.security.web.authentication.logout.LogoutFilter@3d605657, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@15d2ea6b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7ac1161f, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3f2d2f22, org.springframework.security.web.access.ExceptionTranslationFilter@4e4c05a0, org.springframework.security.web.access.intercept.AuthorizationFilter@5b29d699]] (1/1)
    2023-02-09T21:10:24.072Z DEBUG 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /parsing/parseAFile?filename=%22test%22
    2023-02-09T21:10:24.073Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/12)
    2023-02-09T21:10:24.073Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/12)
    2023-02-09T21:10:24.074Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/12)
    2023-02-09T21:10:24.100Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/12)
    2023-02-09T21:10:24.106Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking CorsFilter (5/12)
    2023-02-09T21:10:24.116Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking CsrfFilter (6/12)
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.csrf.CsrfFilter         : Did not protect against CSRF since request did not match CsrfNotRequired [TRACE, HEAD, GET, OPTIONS]
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (7/12)
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.s.w.a.logout.LogoutFilter            : Did not match request to Ant [pattern='/logout', POST]
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking RequestCacheAwareFilter (8/12)
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.s.w.s.HttpSessionRequestCache        : matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (9/12)
    2023-02-09T21:10:24.126Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (10/12)
    2023-02-09T21:10:24.126Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (11/12)
    2023-02-09T21:10:24.127Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking AuthorizationFilter (12/12)
    2023-02-09T21:10:24.127Z TRACE 19384 --- [nio-8081-exec-1] estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@adc8e17]
    2023-02-09T21:10:24.139Z TRACE 19384 --- [nio-8081-exec-1] estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@adc8e17] using org.springframework.security.authorization.AuthenticatedAuthorizationManager@55a93588
    2023-02-09T21:10:24.140Z TRACE 19384 --- [nio-8081-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
    2023-02-09T21:10:24.140Z TRACE 19384 --- [nio-8081-exec-1] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
    2023-02-09T21:10:24.140Z TRACE 19384 --- [nio-8081-exec-1] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
    2023-02-09T21:10:24.141Z TRACE 19384 --- [nio-8081-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]]
    2023-02-09T21:10:24.142Z TRACE 19384 --- [nio-8081-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
    

    So I understand I am missing roles mapping, but there is no any documentation or tutorials how to do that, and so confused that without filter chain authorisation work absolutely fine as expected, all roles goes fine as well

    I just tried as you recommended:
    http.oauth2ResourceServer(Customizer.withDefaults())
    and it results in error
    Factory method 'securityFilterChain' threw exception with message: Jwt and Opaque Token are the only supported formats for bearer tokens in Spring Security and neither was found. Make sure to configure JWT via http.oauth2ResourceServer().jwt() or Opaque Tokens via http.oauth2ResourceServer().opaqueToken().

    I tried doing requests via different tools: postman, insomnia, browser console, react frontend - all results in 403

    thanks in advance

    You can use http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) if you are using JWTs. You might want to read this section to know how to map the authorities https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-authorization-extraction

  • Security log is the following:
  • Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@24482a4f, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3140ad41, org.springframework.security.web.context.SecurityContextHolderFilter@790f4933, org.springframework.security.web.header.HeaderWriterFilter@2526d5f9, org.springframework.web.filter.CorsFilter@2e09c51, org.springframework.security.web.csrf.CsrfFilter@463a1f47, org.springframework.security.web.authentication.logout.LogoutFilter@3d605657, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@15d2ea6b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7ac1161f, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3f2d2f22, org.springframework.security.web.access.ExceptionTranslationFilter@4e4c05a0, org.springframework.security.web.access.intercept.AuthorizationFilter@5b29d699]] (1/1)
    2023-02-09T21:10:24.072Z DEBUG 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /parsing/parseAFile?filename=%22test%22
    2023-02-09T21:10:24.073Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/12)
    2023-02-09T21:10:24.073Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/12)
    2023-02-09T21:10:24.074Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/12)
    2023-02-09T21:10:24.100Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/12)
    2023-02-09T21:10:24.106Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking CorsFilter (5/12)
    2023-02-09T21:10:24.116Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking CsrfFilter (6/12)
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.csrf.CsrfFilter         : Did not protect against CSRF since request did not match CsrfNotRequired [TRACE, HEAD, GET, OPTIONS]
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (7/12)
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.s.w.a.logout.LogoutFilter            : Did not match request to Ant [pattern='/logout', POST]
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking RequestCacheAwareFilter (8/12)
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.s.w.s.HttpSessionRequestCache        : matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided
    2023-02-09T21:10:24.122Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (9/12)
    2023-02-09T21:10:24.126Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (10/12)
    2023-02-09T21:10:24.126Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (11/12)
    2023-02-09T21:10:24.127Z TRACE 19384 --- [nio-8081-exec-1] o.s.security.web.FilterChainProxy        : Invoking AuthorizationFilter (12/12)
    2023-02-09T21:10:24.127Z TRACE 19384 --- [nio-8081-exec-1] estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@adc8e17]
    2023-02-09T21:10:24.139Z TRACE 19384 --- [nio-8081-exec-1] estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@adc8e17] using org.springframework.security.authorization.AuthenticatedAuthorizationManager@55a93588
    2023-02-09T21:10:24.140Z TRACE 19384 --- [nio-8081-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
    2023-02-09T21:10:24.140Z TRACE 19384 --- [nio-8081-exec-1] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
    2023-02-09T21:10:24.140Z TRACE 19384 --- [nio-8081-exec-1] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
    2023-02-09T21:10:24.141Z TRACE 19384 --- [nio-8081-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]]
    2023-02-09T21:10:24.142Z TRACE 19384 --- [nio-8081-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
    

    So I understand I am missing roles mapping, but there is no any documentation or tutorials how to do that, and so confused that without filter chain authorisation work absolutely fine as expected, all roles goes fine as well

  • I just tried as you recommended:
    http.oauth2ResourceServer(Customizer.withDefaults())
    and it results in error
    Factory method 'securityFilterChain' threw exception with message: Jwt and Opaque Token are the only supported formats for bearer tokens in Spring Security and neither was found. Make sure to configure JWT via http.oauth2ResourceServer().jwt() or Opaque Tokens via http.oauth2ResourceServer().opaqueToken().
  • I tried doing requests via different tools: postman, insomnia, browser console, react frontend - all results in 403
  • thanks in advance

    Hello Buddy ,

    Did you resolved this issue? I'm facing the same issue. could you please give me your input?
    Thanks