18

I added a simple swagger UI to my existing springboot REST API by adding the following class to my code:

@EnableSwagger2
@Configuration
public class SwaggerConfig {                                    
    @Bean
    public Docket api() { 
        return new Docket(DocumentationType.SWAGGER_2)  
            .select()
            .paths(PathSelectors.regex("/v1.*"))
            .build()
            .pathMapping("/")
            .apiInfo(metadata());
    }


    private ApiInfo metadata() {
        return new ApiInfoBuilder()
          .title("My awesome API")
          .description("Some description")
          .version("1.0")
          .build();
      }
}

My problem is that the API should be public, but the swagger docs should not. I would like a way of requesting authentication to the swagger documentation, anyone knows any simple way of achieving this?

I tried to google it but I could only find OAth stuff, but this is authentication for the endpoints not the swagger documentation...

Ernani
  • 1,009
  • 3
  • 15
  • 26
  • [this helpful for me with more detail ](https://stackoverflow.com/questions/46999940/spring-boot-how-to-specify-the-passwordencoder) – BertramLAU Nov 23 '19 at 15:08

3 Answers3

22

Swagger docs will be available at /v2/api-docs endpoint when swagger integrated with spring boot application.

Inorder to protect the resource , make use of spring security and restrict the endpoint for accessing the docs

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

Security configuration : restricting access to the endpoint only to the users

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()               
                .antMatchers("/v2/api-docs").authenticated()
                .and()
                .httpBasic();

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

Additionally, swagger-ui.html can also be secured based on the requirement.

Barath
  • 5,093
  • 1
  • 17
  • 42
  • 1
    Thanks a lot, that was exactly what I was looking for – Ernani Aug 21 '17 at 15:49
  • @Barath: so how will user details be passed to load swagger UI ? I mean, will login pop up come automatically if I secure swagger UI using above code ? I have JWT authentication for business end points and I wish same to be used for swagger UI too. – Sabir Khan Dec 07 '18 at 05:55
  • 1
    @Barath: I guess, things are a bit complicated with JWT in place. I don't get pop up but **Failed to load API definition. undefined http://localhost:8080/mycontext/v2/api-docs** ...Since you coded with `inMemoryAuthentication` so you might be getting pop up. Also, hitting swagger UI doesn't land control to my JWT filter. – Sabir Khan Dec 07 '18 at 06:06
  • Post a new question need to understand the setup. You need to have different matchers to handle it if you have different filters registered – Barath Dec 07 '18 at 06:22
  • can you share the cull class..because mine is not working – aswzen Mar 18 '19 at 16:28
  • could you please open a new question with your code please – Barath Mar 18 '19 at 17:20
  • @SabirKhan Have you been able to resolve this, or have you opened a new question? If so, please share the link – Yazan Khalaileh Mar 31 '20 at 20:02
4

Here's a an alternative solution. This is about limiting access to swagger only in development/qa environment. The production environment will not have access to Swagger. 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/");
    }
  }
}
Abdul Rahman
  • 1,833
  • 1
  • 21
  • 21
1

I use this boiler plater to configure and secure swagger

@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
        .antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**")
        .authenticated().and().httpBasic();

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
    }

}
umunBeing
  • 514
  • 1
  • 5
  • 15