SecurityContextHolder with AbstractPreAuthenticatedProcessingFilter
See original GitHub issueHi,
I’m trying to rate limit my API using an API key from the URL I have my API secured by an API key using this method:
@Configuration
@EnableWebSecurity
public class APISecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${principal.hashed.key}")
private String principalHashedKey;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
APIKeyAuthFilter filter = new APIKeyAuthFilter();
filter.setAuthenticationManager(authentication -> {
String urlApiKey = (String) authentication.getPrincipal();
if (!BCrypt.checkpw(urlApiKey, principalHashedKey)) {
throw new BadCredentialsException("The API key was not found or not the expected value.");
}
authentication.setAuthenticated(true);
return authentication;
});
httpSecurity
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", "/documentation.html")
.permitAll()
.anyRequest()
.authenticated()
.and()
.addFilter(filter)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
and the filter:
public class APIKeyAuthFilter extends AbstractPreAuthenticatedProcessingFilter {
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
return request.getParameter("api_key");
}
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return "N/A";
}
}
What is happening is I’m getting the api_key from the url and then check it against the hashed api_key. If they match then the request passes. Everithing works well.
My problem is that when using this:
bucket4j.filters[0].rate-limits[0].execute-condition=@securityService.isAuthorized()
@Service
public class SecurityService {
public boolean isAuthorized() {
return SecurityContextHolder.getContext().getAuthentication() != null &&
SecurityContextHolder.getContext().getAuthentication().isAuthenticated();
}
}
the SecurityContextHolder.getContext().getAuthentication() is always null but if I try to use it in my controller it is not null anymore. I guess it has something to do with the fact that I’m using a filter and not the classic approach with username and pass. Is there something I can do to get the status of auth?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:6 (1 by maintainers)
Top Results From Across the Web
spring-security/AbstractPreAuthenticatedProcessingFilter.java ...
public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFilterBean ... securityContextHolderStrategy = SecurityContextHolder.
Read more >AbstractPreAuthenticatedProces...
public abstract class AbstractPreAuthenticatedProcessingFilter extends ... Sets the SecurityContextRepository to save the SecurityContext on authentication ...
Read more >Spring Security : Set Remember me Service while using ...
How to configure spring security to set remember me service while using a customAuthenticationFilter extending AbstractPreAuthenticatedProcessingFilter and ...
Read more >org.springframework.security.web ... - Download JAR files
AbstractPreAuthenticatedProcessingFilter maven / gradle build tool code. ... SecurityContextHolder; import org.springframework.security.web.
Read more >Spring Security Reference - Framework Repositories
PRE_AUTH_FILTER, AbstractPreAuthenticatedProcessingFilter Subclasses, N/A ... The security context is established by calling SecurityContextHolder.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

Took me a day to figure it out. This post made me realize that Spring security context is only accessible after some security filter has been applied first. Depending on how many filters you have, filter-order must be high enough, so that Spring security context is available when the Bucket4J filter is applied.
I solved my issue by adding this line in spring security config class:
.addFilterAfter(context.getBean(ServletRequestFilter.class), APIKeyAuthFilter.class)and have the filter order set to a high value. The class looks like this now:
So now I have the
ServletRequestFilterregistered in thespringSecurityFilterChainand once again after it. This was the only combination I found that worked for my case. The full code is here: https://github.com/cod-r/docs