I tried integrating API-Key authentication mechanism to Spring Boot Application in the following way:
- Created a
CustomAPIKeyAuthFilter
that extendsAbstractPreAuthenticatedProcessingFilter
where it gets the preauthenticated principal from the headers of the request.
public class CustomAPIKeyAuthFilter extends AbstractPreAuthenticatedProcessingFilter {
private String principalRequestHeader;
private String principalAuthKey;
public CustomAPIKeyAuthFilter(String principalRequestHeader, String principalAuthKey) {
this.principalRequestHeader = principalRequestHeader;
this.principalAuthKey = principalAuthKey;
}
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
return request.getHeader(principalRequestHeader);
}
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
// anything to be returned here??
return "TBD";
}
}
- Created
WebSecurityConfig
that extendsWebSecurityConfigurerAdapter
. In this one, the custom filter is injected inside the overridden methodprotected void configure(HttpSecurity httpSecurity) {}
@EnableWebSecurity
@Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${superuser}")
private String principalRequestHeader;
@Value("${superuserauthkey}")
private String principalRequestValue;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
CustomAPIKeyAuthFilter filter = new CustomAPIKeyAuthFilter(principalRequestHeader, principalRequestValue);
filter.setAuthenticationManager(new AuthenticationManager() {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String principal = (String) authentication.getPrincipal();
if (principalRequestValue.equals(principal)){
authentication.setAuthenticated(true);
} else {
throw new BadCredentialsException("Missing API Key");
}
return authentication;
}
});
httpSecurity.
cors().and().
csrf().disable().authorizeRequests()
.antMatchers("**swagger**").permitAll() // this is the part that is not working for me
.anyRequest().authenticated()
.and()
.addFilter(filter)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
As you can see from the comment above, even though I used permitAll
, I get the error 401 No pre-authenticated principal found in request
at runtime if I try to access Swagger UI which was working before introducing spring-boot-starter-security related dependencies in my pom.xml. Is there a better way to exclude swagger UI alone from the list of URL end points that need API-key based authentication ?
Note: I am using springfox-swagger2 implementation of Swagger and the version used is 2.8.0.
Swagger have api endpoint which should be allowed in security level, add the below snippet in
WebSecurityConfig.class
You could also try
permitAll()
to the patterns included.This will exclude the swagger from being authenticated.