How to configure Spring Security to allow Swagger URL to be accessed without authentication

Spring MvcSwaggerSwagger UiSwagger 2.0Springfox

Spring Mvc Problem Overview


My project has Spring Security. Main issue: Not able to access swagger URL at http://localhost:8080/api/v2/api-docs. It says Missing or invalid Authorization header.

Screenshot of the browser window My pom.xml has the following entries

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.4.0</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.4.0</version>
</dependency>

SwaggerConfig :

@Configuration
@EnableSwagger2
public class SwaggerConfig {

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2).select()
    		.apis(RequestHandlerSelectors.any())
    		.paths(PathSelectors.any())
    		.build()
    		.apiInfo(apiInfo());
}

private ApiInfo apiInfo() {
    ApiInfo apiInfo = new ApiInfo("My REST API", "Some custom description of API.", "API TOS", "Terms of service", "[email protected]", "License of API", "API license URL");
    return apiInfo;
}

AppConfig:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.musigma.esp2" })
@Import(SwaggerConfig.class)
public class AppConfig extends WebMvcConfigurerAdapter {

// ========= Overrides ===========

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LocaleChangeInterceptor());
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
      .addResourceLocations("classpath:/META-INF/resources/");
 
    registry.addResourceHandler("/webjars/**")
      .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

web.xml entries:

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		com.musigma.esp2.configuration.AppConfig
		com.musigma.esp2.configuration.WebSecurityConfiguration
		com.musigma.esp2.configuration.PersistenceConfig
		com.musigma.esp2.configuration.ACLConfig
		com.musigma.esp2.configuration.SwaggerConfig
	</param-value>
</context-param>

WebSecurityConfig:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan(basePackages = { "com.musigma.esp2.service", "com.musigma.esp2.security" })
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		httpSecurity
		.csrf()
			.disable()
		.exceptionHandling()
			.authenticationEntryPoint(this.unauthorizedHandler)
			.and()
		.sessionManagement()
			.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
			.and()
		.authorizeRequests()
			.antMatchers("/auth/login", "/auth/logout").permitAll()
			.antMatchers("/api/**").authenticated()
			.anyRequest().authenticated();

		// custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
		httpSecurity.addFilterBefore(loginFilter(), UsernamePasswordAuthenticationFilter.class);

		// custom Token based authentication based on the header previously given to the client
		httpSecurity.addFilterBefore(new StatelessTokenAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
	}
}

Spring Mvc Solutions


Solution 1 - Spring Mvc

Adding this to your WebSecurityConfiguration class should do the trick.

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

Solution 2 - Spring Mvc

I had the same problem using Spring Boot 2.0.0.M7 + Spring Security + Springfox 2.8.0. And I solved the problem using the following security configuration that allows public access to Swagger UI resources.

Answer updated in January 2021 : support Springfox 3

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static final String[] AUTH_WHITELIST = {
            // -- Swagger UI v2
            "/v2/api-docs",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/swagger-ui.html",
            "/webjars/**",
            // -- Swagger UI v3 (OpenAPI)
            "/v3/api-docs/**",
            "/swagger-ui/**"
            // other public endpoints of your API may be appended to this array
    };


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
                // ... here goes your custom security configuration
                authorizeRequests().
                antMatchers(AUTH_WHITELIST).permitAll().  // whitelist Swagger UI resources
                // ... here goes your custom security configuration
                antMatchers("/**").authenticated();  // require authentication for any endpoint that's not whitelisted
    }

}

Solution 3 - Spring Mvc

I updated with /configuration/** and /swagger-resources/** and it worked for me.

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

}

Solution 4 - Spring Mvc

For those who using a newer swagger 3 version org.springdoc:springdoc-openapi-ui

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

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

Solution 5 - Spring Mvc

if your springfox version higher than 2.5, should be add WebSecurityConfiguration as below:

@Override
public void configure(HttpSecurity http) throws Exception {
	// TODO Auto-generated method stub
	http.authorizeRequests()
		.antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui", "/swagger-resources", "/swagger-resources/configuration/security", "/swagger-ui.html", "/webjars/**").permitAll()
		.and()
		.authorizeRequests()
		.anyRequest()
		.authenticated()
		.and()
		.csrf().disable();
}

Solution 6 - Spring Mvc

More or less this page has answers but all are not at one place. I was dealing with the same issue and spent quite a good time on it. Now i have a better understanding and i would like to share it here:

I Enabling Swagger ui with Spring websecurity:

If you have enabled Spring Websecurity by default it will block all the requests to your application and returns 401. However for the swagger ui to load in the browser swagger-ui.html makes several calls to collect data. The best way to debug is open swagger-ui.html in a browser(like google chrome) and use developer options('F12' key ). You can see several calls made when the page loads and if the swagger-ui is not loading completely probably some of them are failing.

you may need to tell Spring websecurity to ignore authentication for several swagger path patterns. I am using swagger-ui 2.9.2 and in my case below are the patterns that i had to ignore:

However if you are using a different version your's might change. you may have to figure out yours with developer option in your browser as i said before.

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

II Enabling swagger ui with interceptor

Generally you may not want to intercept requests that are made by swagger-ui.html. To exclude several patterns of swagger below is the code:

Most of the cases pattern for web security and interceptor will be same.

@Configuration
@EnableWebMvc
public class RetrieveCiamInterceptorConfiguration implements WebMvcConfigurer {

@Autowired
RetrieveInterceptor validationInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
	
	registry.addInterceptor(validationInterceptor).addPathPatterns("/**")
	.excludePathPatterns("/v2/api-docs", "/configuration/ui", 
			"/swagger-resources/**", "/configuration/**", "/swagger-ui.html"
			, "/webjars/**", "/csrf", "/");
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
      .addResourceLocations("classpath:/META-INF/resources/");
 
    registry.addResourceHandler("/webjars/**")
      .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

}

Since you may have to enable @EnableWebMvc to add interceptors you may also have to add resource handlers to swagger similar to i have done in the above code snippet.

Solution 7 - Spring Mvc

Some security config and you are ready with swagger open to all

For Swagger V2

@Configuration
@EnableWebSecurity
public class CabSecurityConfig extends WebSecurityConfigurerAdapter {


	private static final String[] AUTH_WHITELIST = {
			// -- swagger ui
			"/v2/api-docs", 
			"/swagger-resources/**", 
		    "/configuration/ui",
			"/configuration/security", 
			"/swagger-ui.html",
			"/webjars/**"
	};

	@Override
	protected void configure(HttpSecurity http) throws Exception {

		// ... here goes your custom security configuration
		http.authorizeRequests().
		antMatchers(AUTH_WHITELIST).permitAll(). // whitelist URL permitted
		antMatchers("/**").authenticated(); // others need auth
	}

}

For Swagger V3

@Configuration
@EnableWebSecurity
public class CabSecurityConfig extends WebSecurityConfigurerAdapter {


	private static final String[] AUTH_WHITELIST = {
			// -- swagger ui
			"/v2/api-docs",
            "/v3/api-docs",  
			"/swagger-resources/**", 
			"/swagger-ui/**",
			 };

	@Override
	protected void configure(HttpSecurity http) throws Exception {

		// ... here goes your custom security configuration
		http.authorizeRequests().
		antMatchers(AUTH_WHITELIST).permitAll(). // whitelist URL permitted
		antMatchers("/**").authenticated(); // others need auth
	}

}

Solution 8 - Spring Mvc

Limiting only to Swagger related resources:

.antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/springfox-swagger-ui/**");

Solution 9 - Spring Mvc

Here's a complete solution for Swagger with Spring Security. We probably want to only enable Swagger in our development and QA environment and disable it in the production environment. So, I am using a property (prop.swagger.enabled) as a flag to bypass spring security authentication for swagger-ui only in development/qa environment.

@Configuration
@EnableSwagger2
public class SwaggerConfiguration extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {

@Value("${prop.swagger.enabled:false}")
private boolean enableSwagger;

@Bean
public Docket SwaggerConfig() {
    return new Docket(DocumentationType.SWAGGER_2)
            .enable(enableSwagger)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.your.controller"))
            .paths(PathSelectors.any())
            .build();
}

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

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (enableSwagger) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
  }
}

Solution 10 - Spring Mvc

I am using Spring Boot 5. I have this controller that I want an unauthenticated user to invoke.

  //Builds a form to send to devices   
@RequestMapping(value = "/{id}/ViewFormit", method = RequestMethod.GET)
@ResponseBody
String doFormIT(@PathVariable String id) {
    try
    {
        //Get a list of forms applicable to the current user
        FormService parent = new FormService();

Here is what i did in the configuuration.

  @Override
   protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers(
                    "/registration**",
                    "/{^[\\\\d]$}/ViewFormit",

Hope this helps....

Solution 11 - Spring Mvc

Just for enabling Swagger with Spring boot 2.5.4 and Springfox Swagger2:3.0.0 the following changes were sufficient for me:- .authorizeRequests().antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui/**").permitAll().and()

Thanks to everyone for their suggestions in this thread!

Solution 12 - Spring Mvc

Considering all of your API requests located with a url pattern of /api/.. you can tell spring to secure only this url pattern by using below configuration. Which means that you are telling spring what to secure instead of what to ignore.

@Override
protected void configure(HttpSecurity http) throws Exception {
  http
    .csrf().disable()
     .authorizeRequests()
      .antMatchers("/api/**").authenticated()
      .anyRequest().permitAll()
      .and()
    .httpBasic().and()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

Solution 13 - Spring Mvc

Add a Bean like this:

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange()
	.pathMatchers(
		"/v2/api-docs",
		"/swagger-ui/**",
		"/swagger-resources/**",
		"/*/swagger-resources/**",
		"/*/v2/api-docs")
	.permitAll()
	.and()
	.authorizeExchange()
	.anyExchange()
	.permitAll();
http.httpBasic().disable();
http.csrf().disable();
return http.build();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionshubhendu_shekharView Question on Stackoverflow
Solution 1 - Spring MvcStijn MallerView Answer on Stackoverflow
Solution 2 - Spring MvcnaXa stands with UkraineView Answer on Stackoverflow
Solution 3 - Spring MvcAkshata SuvarnaView Answer on Stackoverflow
Solution 4 - Spring MvcDennis GlossView Answer on Stackoverflow
Solution 5 - Spring Mvcduliu1990View Answer on Stackoverflow
Solution 6 - Spring MvcchanderdevxView Answer on Stackoverflow
Solution 7 - Spring MvcRupesh KumarView Answer on Stackoverflow
Solution 8 - Spring Mvcm52509791View Answer on Stackoverflow
Solution 9 - Spring MvcAbdul RahmanView Answer on Stackoverflow
Solution 10 - Spring Mvcsmac2020View Answer on Stackoverflow
Solution 11 - Spring MvcSPSView Answer on Stackoverflow
Solution 12 - Spring MvcSidduView Answer on Stackoverflow
Solution 13 - Spring MvcImranmadbarView Answer on Stackoverflow