Reputation: 1433
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);
}
}
Upvotes: 140
Views: 304964
Reputation: 104
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();
Upvotes: 4
Reputation: 471
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();
}
}
http://{your host}:{your port}/swagger-ui/index.html
http://{your host}:{your port}/v3/api-docs
http://{your host}:{your port}/v3/api-docs.yaml
Upvotes: 6
Reputation: 17980
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/**");
}
Upvotes: 2
Reputation: 5460
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();
}
Upvotes: 0
Reputation: 303
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!
Upvotes: 1
Reputation: 37916
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
}
}
Upvotes: 90
Reputation: 214
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
}
}
Upvotes: 5
Reputation: 10704
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....
Upvotes: 1
Reputation: 2831
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/**");
}
}
Upvotes: 33
Reputation: 1843
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/");
}
}
}
Upvotes: 3
Reputation: 467
Limiting only to Swagger related resources:
.antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/springfox-swagger-ui/**");
Upvotes: 2
Reputation: 3043
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/**");
}
}
Upvotes: 239
Reputation: 147
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.
Upvotes: 5
Reputation: 23
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);
}
Upvotes: 1
Reputation: 367
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();
}
Upvotes: 5
Reputation: 339
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/**");
}
Upvotes: 33