spring-bootspring-securityswaggerspring-security-rest

Unable to use permitAll() with Spring Boot 2.3.4 to allow access to Swagger UI after integrating with API-Key Authentication


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.


Solution

  • 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.