I am trying to follow the API Key authentication code from this answer: https://stackoverflow.com/a/48448901
I created my filter class:
package com.propfinancing.CADData.web;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
public class PullAPIKeyFromHeaderFilter extends AbstractPreAuthenticatedProcessingFilter {
private String apiKeyHeaderName;
public PullAPIKeyFromHeaderFilter(String apiKeyHeaderName) {
this.apiKeyHeaderName = apiKeyHeaderName;
}
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
String headerValue = request.getHeader(apiKeyHeaderName);
return request.getHeader(headerValue);
}
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return apiKeyHeaderName;
}
}
And then I implemented my security configuration:
package com.propfinancing.CADData.web;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
@Configuration
@EnableWebSecurity
@Order(1)
public class APIKeySecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${caddata.apiKey.header.name}")
private String apiKeyHeaderName;
@Value("${caddata.apiKey}")
private String apiKey;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
PullAPIKeyFromHeaderFilter pullAPIKeyFromHeaderfilter = new PullAPIKeyFromHeaderFilter(apiKeyHeaderName);
AuthenticationManager authManager = new AuthenticationManager() {
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String principal = (String) authentication.getPrincipal();
if (!apiKey.equals(principal))
throw new BadCredentialsException("Invalid API key");
authentication.setAuthenticated(true);
return authentication;
}
};
pullAPIKeyFromHeaderfilter.setAuthenticationManager(authManager);
httpSecurity.antMatcher("/**");
httpSecurity.addFilter(pullAPIKeyFromHeaderfilter);
httpSecurity.requiresChannel().anyRequest().requiresSecure();
httpSecurity.csrf().disable();
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry urlAuthConfigurer = httpSecurity.authorizeRequests();
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.AuthorizedUrl authorizedUrl = urlAuthConfigurer.anyRequest();
authorizedUrl.authenticated();
}
}
When I do an external call to the application with the header as part of the request, I get a 403 Forbidden response. I can see the filter pulling the key from the header. That part is working.
But, the authenticate() method is not being called to check if the header is valid. I am not sure what I missed, the code looks the same to me.
Any ideas?
CodePudding user response:
Looks like the wrong base class, per https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.html :
The purpose is then only to extract the necessary information on the principal from the incoming request, rather than to authenticate them.
Try extending https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html instead.
CodePudding user response:
I was not able to get the code above to work, but I changed it to use the second answer on that thread https://stackoverflow.com/a/63852212 which worked as expected.