Allow anonymous access to springdoc-openapi-ui with Spring Security - java

How to allow anonymous access to springdoc-openapi-ui (OpenAPI 3.0 /swagger-ui.html) in a Spring Boot application secured by Spring Security?

To use springdoc-openapi-ui /swagger-ui.html, allow anonymous access to the following endpoints in the WebSecurityConfigurerAdapter using permitAll method:
/v3/api-docs/**
/swagger-ui/**
/swagger-ui.html
Example:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.
.authorizeRequests()
.antMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic(); //or anything else, e.g. .oauth2ResourceServer().jwt()
}
}
Make sure a project has the following dependencies:
org.springdoc:springdoc-openapi-ui
org.springdoc:springdoc-openapi-security

Additionally to Evgeniy's answer, I'd add the proper configuration to avoid conflicts with document fetching used in Swagger's UI (such js, html, images and other files), also in the SecurityConfig class like this:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//Other configuration methods
#Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers("/v3/api-docs/**", "/swagger-ui/**");
}
}
Without this configuration, even though the UI looks like It's loaded, a 401: Unauthorized may arise on the background calls when loading the above mentioned files.

For obtaining access in spring webflux you have to do the following, tested with spring-doc version 1.5.2:
The swagger webpage was failing on html resources with the path /webjars/swagger-ui.
#Configuration
#EnableWebFluxSecurity
public class SecurityConfig {
#Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange()
.pathMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", "/webjars/swagger-ui/**")
.permitAll()
.anyExchange()
.authenticated()
.and()
.build();
}
}

Related

Spring Disable Swagger-ui for production

I know how to disable swagger for production - i only need to add annotation #Profile("!prod") in configuration class:
#Configuration
#EnableSwagger2
#RequiredArgsConstructor
#Profile("!prod")
public class SwaggerConfig {
result of adding annotation
But the result is, that the swagger-ui.html still is available in browser, only its empty. I wonder is there solution to disable it fully, so the page will not load?
this could be simply done with spring-security by blocking the url for the production environment. Please try :
Add dependency (if you are using spring-boot) to pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Add configuration file :
#Configuration
#Profile("prod")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**/swagger-ui.html").denyAll();
}
}
It will send 403 forbidden status.
Okey #zpavel its good solution, thank you. I just already had such spring security configuration, and when i added yours, i got error "#Order on WebSecurityConfigurers must be unique.", so i added to one class #Order(1), and to the other one #Order(2). Unfortunately the .antMatchers("/**/swagger-ui.html").denyAll(); denied all request even those who were not swagger calls, i don't know why.
Hovewer i modified Your solution and it worked for me:
#Value("${spring.profiles.active}")
private String activeProfile;
#Override
public void configure(HttpSecurity http) throws Exception {
if(activeProfile.equals("prod")){
http.authorizeRequests()
.antMatchers("/something").permitAll()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/swagger-ui.html", "/webjars/**").denyAll()
.antMatchers("/something").permitAll()
.anyRequest().authenticated();
} else {
http.authorizeRequests()
.antMatchers("/something").permitAll()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/swagger-ui.html", "/webjars/**").permitAll()
.antMatchers("/something").permitAll()
.antMatchers("/something").permitAll()
.anyRequest().authenticated();
}
}

How can I whitelist Domain or IP address in a Rest API application in which we are using springboot?

I'm implementing REST API and we are directly streaming the response using StreamingResponseBody of springboot. We are receiving query parameter through JSON and we are sending the database response by directly streaming.
We want to lock down access to the URL to a particular Domain or set of IP address - how can we achieve this?
If you are using Java Configuration for Spring Boot Security than you have to use
hasIpAddress()
in SecurityConfig class that extends WebSecurityConfigurerAdapter.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/api/example/**").hasIpAddress("1.1.1.1")
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.csrf().disable();
}
// Rest of Code ...
}

Spring-Boot security - Resource folder doesn't work

I have a quick issue which am not really sure how to sort this out yet.
The issue is that, I'm using Thymeleaf, and was working perfectly fine until I've introduced the Springboot security. Since then, the styling isn't working at all. Looks like the static folder isn't seen for some reason. I've tried several structures to make it work but still no luck. I've tried to include in resource folder static folder, then resource folder (again) with no luck. I've also tried to rename the static into public, still no luck. I've noticed that if you include the URL somewhere on the web it works but if you include the URL somewhere on your local machine doesn't work. So I'm 100% sure there is a problem with the structure of the folders or the Spring configuration.
Any help, would be really much appreciated.
Spring security configuration class:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.failureUrl("/login?error")
.defaultSuccessUrl("/default")
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/", "/static/**").permitAll()
.antMatchers("/createUser").hasRole("ADMIN")
.anyRequest().authenticated();
}
}
WebConfig class:
#Configuration
#EnableWebMvc
public class WebAppConfig {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}

Spring 4 security rule definition

I had updated spring security from 3x to 4.0.1.RELEASE. Then I finally had the change to fully remove old XML, and replace it with pure java config. But my security isn't working properly.
Problem:
my default login page does not authorize, under POST /login.htm I have 404.
my main app can run as unauthorized
because I have 404 on login POST, I am not entering UserDetailsService
all beans are provided into this configuration, I have no context start problems
My configuration file:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan(basePackages = {"com.dal.dao.security", "com.services.security"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
LocalUserDao userDao;
#Autowired
UserRoleMapper roleMapper;
#Autowired
StandardPasswordEncoder passwordEncoder;
private UserDetailsService methodSecurityService() throws Exception {
return new UserDetailsServiceImpl(userDao, roleMapper);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(methodSecurityService()).passwordEncoder(passwordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/*")
.authenticated()
.and()
.formLogin()
.loginPage("/login.htm").failureUrl("/login.htm?error")
.usernameParameter("username")
.passwordParameter("password")
.and().logout().logoutSuccessUrl("/index.htm")
.and().csrf()
.and().exceptionHandling().accessDeniedPage("/403");
}
}
Could anyone help me with this? I have already watched few no-xml configuration, but they don't seem to be working on my example.
Source of my code can be found here.
I think the fix is simple (i hope) you didn't advise that anyone can access your login form:
http.authorizeRequests()
.antMatchers("/*")
.authenticated()
.and()
.formLogin()
.loginPage("/login.htm").failureUrl("/login.htm?error")
.usernameParameter("username")
.passwordParameter("password")
.permitAll() // ADD THIS LINE
.and().logout().logoutSuccessUrl("/index.htm")
.and().csrf()
.and().exceptionHandling().accessDeniedPage("/403");
Essentially you are redirecting users to login page without enabling unauthenticated access to it. Basically you are asking them to authenticate to view the authentication form :).
From Spring Security:
Granting access to the formLogin() URLs is not done by default since
Spring Security needs to make certain assumptions about what is
allowed and what is not. To be secure, it is best to ensure granting
access to resources is explicit.

Java Spring common way to implement user authentication

I am new to Java and I trying to write first web application with Spring framework (I have some experience with django/python and sinatra/ruby).
I need to implement user authentication system and have no idea what is the best way to do this correctly. Should I use Spring Security for this? Or there is some another ways?
Since you starting a new application, I strongly urge to use Spring Boot. It will take away a lot of your initial pain in configuring the various aspects of Spring.
As for security, you should go with Spring Security which of course is easy to configure with Spring Boot.
Following this guide, a simple Spring Security configuration which uses in memory authentication would look like:
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
As you can see, the first method is used to configure which parts of the application are to be secured and how, while the second method configures how the users will be authenticated.
One common way to provide a customized way to authenticate users, is to provide a custom UserDetailsService implementation as is done here
A very easy way to configure authentication when you already have configured a DataSource and the user credentials are stored there, is the following:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN").and()
.withDefaultSchema();
}
}
Here is the complete reference of Spring Security. Also here is security part of the Spring Boot documentation. You can find a multitude of sample applications using various aspects of Spring Security here
Initially it may seem that Spring Security is complicated, but once you get the hang of it, you'll appreciate it's extended feature set and customizability.
One final note, when to comes to things like security which are common in so many applications, there is no need to reinvent the wheel! Go with Spring Security (or perhaps Apache Shiro)

Categories