0
votes

I tried integrating API-Key authentication mechanism to Spring Boot Application in the following way:

  1. Created a CustomAPIKeyAuthFilter that extends AbstractPreAuthenticatedProcessingFilter 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";
    }
}
  1. Created WebSecurityConfig that extends WebSecurityConfigurerAdapter. In this one, the custom filter is injected inside the overridden method protected 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.

1

1 Answers

1
votes

Swagger have api endpoint which should be allowed in security level, add the below snippet in WebSecurityConfig.class

@Override
public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**");
}

You could also try permitAll() to the patterns included.This will exclude the swagger from being authenticated.