You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
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.
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