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

16

135

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);
    }
}
Paradox answered 7/6, 2016 at 5:25 Comment(1)
Use the security configuration mentioned on Cannot open Swagger UI in its Version 3 in my Spring Boot Example page.Cia
T
236

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/**");
    }

}
Tortoiseshell answered 7/6, 2016 at 15:26 Comment(10)
If you use swagger-ui you need something like this: .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**","/swagger-resources/configuration/ui","/swagger-ui.html").permitAll()Bongbongo
In my case this rule is working: .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/swagger-resources/configuration/ui", "/swagge‌​r-ui.html", "/swagger-resources/configuration/security").permitAll()Paymar
Needed more rules: .antMatchers("/", "/csrf", "/v2/api-docs", "/swagger-resources/configuration/ui", "/configuration/ui", "/swagger-resources", "/swagger-resources/configuration/security", "/configuration/security", "/swagger-ui.html", "/webjars/**").permitAll()Bicentennial
Thanks for the answer! Is there any security risk allowing access to webjars/** ?Elwandaelwee
very helpful answerRichma
I had to add .., "/swagger-ui/**"... to that listConsolute
@Consolute me too, that's because Springfox 3.0.0 was changed the path.Washtub
This list absolutely didn't work for me.Obstetrics
Could you please add a description of the individual endpoints, why they need to be permitted? I have permitted only /webjars/swagger-ui/**, swagger-ui.html and /v3/api-docs/** and everything seems to be working so far, but perhaps there's some swagger functionality that I overlooked? Or are the configuration endpoints only for springfox?Stephainestephan
If you have actuator enable mappings locally and look at the /actuator/mappings response to make sure you have covered them allManse
L
90

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
    }

}
Lenny answered 25/2, 2018 at 9:15 Comment(8)
after adding this class, I'm able to see swagger-ui but APIs are not accessed via postman even with access_token, getting access forbidden error as below, { "timestamp": 1519798917075, "status": 403, "error": "Forbidden", "message": "Access Denied", "path": "/<some path>/shop" }Bruit
@ChandrakantAudhutwar delete antMatchers("/**").authenticated() statement or replace with your own authentication configuration. Be careful, you better know what you're doing with security.Lenny
yes, it worked. I was thinking of only bypassing swagger-ui, but other APIs as it is secured. now my APIs are also bypassed.Bruit
@ChandrakantAudhutwar you do not need to copy-paste the whole SecurityConfiguration class to your project. You should have your own SecurityConfiguration where you permit requests to Swagger UI resources and keep your APIs secure.Lenny
I have AuthorizationServerConfigurerAdapter implemented class which makes API' authentication.Bruit
@ChandrakantAudhutwar care to explain how you got around your issue? I can access my swagger page as well but when i hit "Try it" the response body is the login page so it's being redirectedLashawn
@ChandrakantAudhutwar it's as if I need to find a way to give swagger a security role so it's not anonymous i see this in my logs: o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@1afeff6, returned: -1 o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry pointLashawn
I know this answer is old, but if you add "/swagger-ui/**" to the list, it will be perfect. Springfox 3.0.0 URL is that way.Washtub
P
34

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/**");

}
Perineurium answered 9/8, 2017 at 12:48 Comment(2)
Perfect! Solved the issue.Legato
This is the one for those using org.springdoc:springdoc-openapi-ui. Thank you!Mug
C
34

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/**");
    }
}
Cleptomania answered 10/4, 2020 at 19:44 Comment(3)
Note: If this stops you from getting a "Authentication Required" error, but just shows you a blank page, I also had to add "/swagger-resources/**" and "/swagger-resources" in that list and it fixed it for me.Dagon
for me .authorizeRequests().antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui/**").permitAll().and() was sufficientRoughhouse
Thanks for posting this; just helped me with Swagger v3.Infralapsarian
P
6

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();
}
Profiteer answered 13/5, 2018 at 9:29 Comment(1)
duliu1990 is right, since springfox 2.5+, all the springfox resources (swagger included) have moved under /swagger-resources. /v2/api-docs is the default swagger api endpoint (of no concern with the UI), which can be overridden with the config variable springfox.documentation.swagger.v2.path springfoxCharmer
D
6

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
    }

}
Digestant answered 15/12, 2020 at 3:17 Comment(1)
I've tested on v3 and can say this configuration works, but if into requests you need Principal, for example to extract username, then Swagger anyway fails, so I avoid spring boot open api.Gherkin
D
6

If you use Spring Boot 3, you need to use: springdoc-openapi-starter-webmvc-ui as it is writen in the doc introduction.

And use security configuration, something like this:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
@RequiredArgsConstructor
public class SecurityConfiguration {

   @Bean
   public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
       return http
               .csrf().disable()
               .authorizeHttpRequests(a -> a
                       .requestMatchers("/v3/**", "/swagger-ui/**").permitAll()
                       .anyRequest().authenticated()
               ).build();
   }
}
  • Swagger UI: http://{your host}:{your port}/swagger-ui/index.html
  • JSON: http://{your host}:{your port}/v3/api-docs
  • yaml: http://{your host}:{your port}/v3/api-docs.yaml
Dupuy answered 21/1, 2023 at 23:49 Comment(2)
I want to add authentication to my swagger. what can I do? So that no one can't see my API list without credentials.Streamer
I feel silly for wandering for so long before finding that I simply had to switch dependencies for Boot 3 (I was still using springdoc-openapi-ui)… Too bad this answer is buried under the old Boot 2-focused ones, haha.Tallou
A
5

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.

Ajaajaccio answered 28/1, 2019 at 12:2 Comment(1)
Why are you adding /csrf in exclusion?Bootless
S
3

Limiting only to Swagger related resources:

.antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/springfox-swagger-ui/**");
Shane answered 2/11, 2019 at 16:11 Comment(1)
for me .authorizeRequests().antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui/**").permitAll().and() was sufficientRoughhouse
P
3

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/");
    }
  }
}
Pelasgian answered 28/11, 2019 at 7:50 Comment(0)
M
2

For Spring Security without the WebSecurityConfigurerAdapter it looks like (springdoc-openapi):

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
    return web -> web.ignoring().requestMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**");
}

See Configuring WebSecurity

Markson answered 23/10, 2022 at 11:10 Comment(0)
D
1

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);
}
Dentil answered 7/3, 2018 at 12:21 Comment(1)
Thank you for this code snippet, which might provide some limited short-term help. A proper explanation would greatly improve its long-term value by showing why this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please edit your answer to add some explanation, including the assumptions you've made.Encrust
F
1

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

Floorage answered 11/5, 2020 at 23:21 Comment(0)
R
1

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!

Roughhouse answered 14/1, 2022 at 10:57 Comment(0)
R
1

For Spring 3 and Swagger springdoc-openapi-starter-webmvc-ui:2.3.0+ I use this config:

    private static final String[] AUTH_WHITELIST = {
        // -- Swagger UI v3 (OpenAPI)
        "/v2/API-docs",
        "/v3/API-docs",
        "/api-docs/**",
        "/swagger-resources/**",
        "/swagger-ui/**",

};

And

    @Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(
                    authorizeHttp -> {
                        authorizeHttp.requestMatchers(AUTH_WHITELIST).permitAll();
                        authorizeHttp.anyRequest().authenticated();
                    });
    return http.build();
Ramayana answered 8/12, 2023 at 12:15 Comment(0)
L
0

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();
}
Lennielenno answered 14/4, 2022 at 3:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.