Spring Disable Swagger-ui for production - java

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();
}
}

Related

Spring Security login problem after migration spring boot 1.5 -> 2.2

I need a help
I'm doing migration spring boot 1.5.17 -> 2.2.1 and everything is fine except spring security.
The problem is I can't login from my login form(tried default login page, same result). Login with basic auth works fine.
I have enabled debug logs with logging.level.org.springframework.security=DEBUG config but still nothing.
What I noticed is when I'm typing wrong credentials - it says 'Username/password is incorrect' so seems the problem is not with password encoder, as spring security version changed.
Than I check browser's networks devtool tab and I can see following: first request goes to /login -> than it redirects to /welcome and than again to /login (see on screen)
Here is my security config
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private UserService userService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/css/**", "/images/**", "/script/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/welcome", true)
.failureUrl("/login/error").permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
}
}
Help please
Thank you in advance

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

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();
}
}

Spring security default form login page failing when antmatcher defined

I am having an issue with Spring 5 form based authentication. This is only an example at this point as I am trying to isolate the issue I'm having. My plan is to include this configuration in a larger project with multiple configurations. The below code (which can be found anywhere) works as expected:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder)
.withUser("user").password(passwordEncoder.encode("password")).roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and().csrf().disable();
}
}
and following code does not work after adding antmatcher:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder)
.withUser("user").password(passwordEncoder.encode("password")).roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.antMatcher("/test/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and().csrf().disable();
}
}
Notice that I've only added an antmatcher to this config. I only want the config to apply to /test/**. And, in this case, I'm not doing anything custom with regards to the form login and would like to get Spring default form. Of course in a real application I would not use the default but this is only for example purposes. My first config displays the default internal Spring form correctly when I GET the following URL: http://localhost:8080/webapp/test/anything. And I can authenticate successfully. For the second configuration I get 404 errors when issuing the same URL.
Spring security does in fact try to redirect to: http://localhost:8080/webapp/login however, the url does not exist. I did try the following change:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/test/**").authorizeRequests().anyRequest().authenticated()
.and().formLogin().permitAll().loginPage("/test/login").loginProcessingUrl("/test/login")
.and().logout().logoutUrl("/test/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
}
This did not work either. I made several attempts, but have not been successful. Is it possible that the default form behavior is disabled when an antmatcher is defined?
This is ideal solution for your requirement
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.requestMatchers().antMatchers("/test/**", "/customLoginPage", "/logout").and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/customLoginPage") //If you don't configure default is "/login"
.usernameParameter("userName").passwordParameter("password") //In case of custom form parameters
.defaultSuccessUrl("/app/user/dashboard") //If you don't configure default is "/"
.failureUrl("/login?error=true") //If you don't configure default is "/login?error"
.and().csrf().disable();
}
Let me explain Some cases how spring security deals with
Case 1:
http.authorizeRequests()
is equals to
http.antMatcher("/**").authorizeRequests()
A proxy filter will be defined and url-pattern for that filter will be "/**". With this type of configuration there will be no problem as it is a wild card. But in some cases we don't want to define wild card "/**" then we should configure requestMatchers correctly otherwise we will end up in lot of unguessable problems.
Case 2:
http.antMatcher("/test/**").authorizeRequests()
Here proxy filter will be added with URL pattern "/test/**" and requests with /login and /logout can't pass through the added filter. To overcome this .requestMatchers() should be used as given below
http
.requestMatchers().antMatchers("/test/**", "/customLoginPage", "/logout")
.and().authorizeRequests()
This means filter with filter mapping as given below
<filter-mapping>
<filter-name>/test/**</filter-name>
<url-pattern>/customLoginPage</url-pattern>
<url-pattern>/logout</url-pattern>
</filter-mapping>
You can try out some of basic examples(Working) from my github repository
After many tries, the following is working for me. Only showing the configure method:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.antMatcher("/test/**")
.authorizeRequests()
.antMatchers("/test/login").permitAll()
.antMatchers("/test/logout").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.jsp").permitAll()
.loginProcessingUrl("/test/login").permitAll()
.failureUrl("/login.jsp?error=yes")
.and()
.logout().permitAll().logoutUrl("/test/logout").permitAll()
.and().csrf().disable();
}
I did need to create my own login form (login.jsp), however the processing of the login form (the POST) is handled by Spring default processing. Really, that was the important piece. Another key point to make is that the login form POST needs to point to /webapp/test/login. I suppose that the Spring configuration needs these additional "tips" in order to trigger the default form processing in cases where the antMatcher call must be present.

Spring Security permit paths with the same suffix

In my JWT authenticated API I want these paths to be accessible without any authentication, and all other endpoints to be disallowed/disabled:
GET /apis/id/{id}
POST /apis
PATCH /apis/id/{id}
DELETE /apis/id/{id}
GET /swagger-ui.html
As you can see most of the above endpoints begin with /apis/id, POST has /apis. Here is my configurations:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.mvcMatchers(HttpMethod.GET,"/apis/id/**").permitAll()
.mvcMatchers(HttpMethod.PATCH,"/apis/id/**").permitAll()
.mvcMatchers(HttpMethod.DELETE,"/apis/id/**").permitAll()
.mvcMatchers(HttpMethod.POST,"/apis", "/apis/").permitAll()
.antMatchers(HttpMethod.GET,"/csrf","/v2/api-docs","/swagger-resources/configuration/ui", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**","/swagger-resources/configuration/ui","/swagger-resources/configuration/security", "/configuration/security").permitAll()// for Swagger UI
.anyRequest().denyAll();
}
}
Only GET /apis/id/{id} and /swagger-ui.html get through. The other endpoints with the identical configs (except for POST) all got rejected (403). I added an exception handler and print out the AuthenticationException message, and it says:
Full authentication is required to access this resource path
How do I make these endpoints public? I feel like I am missing some configurations.
Framworks I am using:
Spring Boot version 2.0.4
Spring Security version 5.1.0
You can take a look at this answer for the possible explanation of you problem.
Invoking antMatcher(String) will override previous invocations of
mvcMatcher(String), requestMatchers(), antMatcher(String),
regexMatcher(String), and requestMatcher(RequestMatcher).
Now that you understand the underlying problem, you can now then change your code into something like this:
http
.requestMatchers()
.antMatchers("/apis/id/**", "/csrf","/v2/api-docs","/swagger-resources/configuration/ui", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**","/swagger-resources/configuration/ui","/swagger-resources/configuration/security", "/configuration/security").permitAll()
.anyRequest().authenticated();

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.

Categories