How to secure only swagger UI page " swagger-ui/index.html#/ " and all other API end points should not be authenticated in Spring boot - spring-boot

I have a requirement where I just need to secure the Swagger UI page. All other endpoints I have written in the application should not be authenticated.
For this, I am using the Spring security starter. I have the Security Config for Spring boot in place. I am trying to authenticate ("/v2/api-docs") because this is where we see all the endpoints in Swagger UI. And also I am trying to permit ("/calculator-controller/callCalculatorServiceUsingPOST") which I see in browser URL when I click on my end point Try it now button and also permitting ("/calculate") which is in my controller. To be safer, I have tried to permit all possible combinations, but no luck.
What Am I missing ???
#Configuration #EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.authorizeRequests()
.antMatchers("/v2/api-docs").authenticated()
.antMatchers("/calculator-
controller/callCalculatorServiceUsingPOST",
"calculator-controller/**", "/calculate")
.permitAll()
.and()
.httpBasic();
}
}

Related

SecurityContextHolder.getContext().getAuthentication() returns null

I'm developing Spring boot and security web application with authorization and resource servers enabled. I have defined a set of users with roles assigned to them and have implemented roles based access to rest endpoints. Besides that my application has straightforward UI with web pages. Those pages display the same data that is on rest. I'm trying to implement the same roles based access to pages with ResourceServerConfig#configure and my current code:
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/rest/products/add").hasAnyRole("ADMIN")
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login.jsf").permitAll()
.loginProcessingUrl("/login")
.defaultSuccessUrl("/login-successful", true)
.and().logout().permitAll();
}
This configuration works perfectly for REST controllers access with bearer token, but authorization with the login form leads to the redirect to the /login-successful and the message
Full authentication is required to access this resourceunauthorized is displayed.
The reason is that SecurityContextHolder.getContext().getAuthentication() for /login-successful request in spite it was correctly initialized in AbstractAuthenticationProcessingFilter#successfulAuthentication at the point of login form post. The same issue with other web pages in my app as well.
What should be added to the above configuration so that make it work for the REST and form login bought ?
Here is indicted that HttpSecurity configuration provided above is enough for authorization with form login to work correctly as far as .anyRequest().authenticated() should pass security context for all the resources in the application.
A similar case is described here but the reason over there is that an url was explicitly ignored in WebSecurity configurer.
The problem was in the fact that I was using deprecated #EnableResourceServer annotation that adds OAuth2AuthenticationProcessingFilter. For the form login authorization flow this is incorrect and that filter was removing authentication object from the SecurityContext. Here is indicated that OAuth2AuthenticationProcessingFilter shouldn't present in the filter chain for the form login authorization flow.
The reason why I was needed #EnableResourceServer annotation is that there are there is the bearer authentication flow in my application alongside with form login.
I replaced #EnableResourceServer annotation and ResourceServerConfigurerAdapter for the bearer authentication flow with Spring Security 5 resource server as http.oauth2ResourceServer() that is in WebSecurityConfigurerAdapter ( see here ). Finally the solution is with the following two WebSecurityConfigurerAdapter-s:
For bearer authorization flow:
#Configuration
#Order(2)
public class SecurityConfigRest extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
NimbusJwtDecoder jwtDecoder = Build custom JWT decoder;
http.csrf().disable()
.requestMatcher(new AntPathRequestMatcher("/rest/**"))
.authorizeRequests()
.mvcMatchers("/products/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt().decoder(jwtDecoder);
}`
and for the form login authorization flow:
#Configuration
#Order(1)
#EnableWebSecurity
public class SecurityConfigFormLogin extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http .requestMatcher(new AntPathRequestMatcher("/view/**"))
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/view/login").permitAll()
.defaultSuccessUrl("/view/login-successful", true)
.and().logout()
.logoutUrl("/view/perform_logout")
.logoutSuccessUrl("/view/login");
}
These two WebSecurityConfigurerAdapter-s make it possible to separate those two authorization flows.
As far as Spring Security 5 resource server supports only JWT or Opaque tokens ( see here ) it requires additional configuration. Here is a detailed description of such a configuration for Spring Security 5 resource server.

Spring boot how to have Thymeleaf web page and REST API with different authentications Schemes

Like the question said, how we can configure Spring Security to have form authentication for the Thymeleaf web page part of the project, and JWT authentication for the REST API part of the project?, because we like to have both projects on the same container and not to have to resource to external Tomcat Application Server to have the same Security Config (SSL, Ciphers, Certificates, ETC.).
So far we don't found how to do it, but if you can have a Thymeleaf and REST API on the same project i think it is possible to configure Spring Security to have to ways of authentication on the project.
You can have this behavior by adding two WebSecurityConfigurerAdapter beans as follows:
#Order(1) - /api/** protected by basic auth, in your case JWT
authentication.
#Order(2) - /website/** protected by form login, in your case
Thymeleaf login.
View docs for Spring Boot and sample code here.
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(1)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().hasRole("API_USER")
.and()
.httpBasic();
}
}
#Configuration
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/website/**").hasRole("ADMIN")
.and()
.formLogin()
.and()
.logout().permitAll()
;
}
}
}

How to support basic authentication and bearer authentication for the REST API project

I am new to Spring Security & still learning it so my question can be naive please bear with it.
I have Sprint Boot Rest API project which exposes certain APIs. I have already implemented the bearer token based authentication for all the APIs.
e.g /user , /resource, /appointment
Now for few apis for a particular controller I would like to have the basic authentication implemented. These Apis will be consumed by another service which is not exposed to public.
In order to have the security for the APIs I would like to have basic authentication in place for these apis.
e.g /internal/api1 , internal/api2 .. and so on
I am not able to distinguished between urls in the ResourceServerConfigurerAdapter & WebSecurityConfigurerAdapter. Also not sure which should be used for adding basicAuth() using the antmatchers
What you want, by reading your problem, is to have two authentication types (token and httpBasic) for two diffetent endpoints. It can be achieved by creating two different WebSecurityConfigurerAdapter beans. Spring Boot enables this and can be done like bellow:
#Order(1) - /resource|user|appointment/** protected by bearer token authentication.
#Order(2) - /internal/** protected by basic auth.
View docs for Spring Boot and sample code here.
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(1)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/resource/**")
.antMatcher("/user/**")
.antMatcher("/appointment/**")
.authorizeRequests()
.anyRequest().authenticated()
.and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
#Configuration
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/internal/**")
.and()
.httpBasic();
}
}
}

Spring Boot Security - Multiple configurations

I'm working (and struggling a little bit) on an example using spring-boot with spring security.
My system is using a web app and also provide an REST-API, so i would like to have form based security (web) and basic auth (resp api).
As the spring documentation recommend (https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#multiple-httpsecurity), I need to create a multi http web security configuration.
The main code works, but if I use Postman for the test of my RestApi following use-case does not work.
All GET-requests to /restapi/ working without authentication (statuscode 200)
All POST-requests to /restapi/ without the BASIC Auth Header are working (statuscode 401)
All POST-requests to /restapi/ with a correct BASIC Auth Header are work (statuscode 200)
BUT all requests with a wrong BASIC Auth header (f.e. user1/1234567) are returning the HTML-Loginpage defined in the first WebSecurityConfigurerAdapter (FormWebSecurityConfigurerAdapter)
Does anyone has an idea - what is wrong with my configuration?
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
private static RestAuthenticationAccessDeniedHandler restAccessDeniedHandler;
#Autowired
public void configureAuth(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication()
.withUser("admin").password("{noop}12345678").roles("ADMIN").and()
.withUser("user").password("{noop}12345678").roles("USER");
}
#Configuration
#Order(1)
public static class RestWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/restapi/**")
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/restapi/**").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(UNAUTHORIZED))
.and()
.exceptionHandling().accessDeniedHandler(restAccessDeniedHandler) ;
}
}
/*
Ensures that any request to our application requires the user to be authenticated (execpt home page)
Requests matched against "/css/**", "/img/**", "/js/**", "/index.html", "/" are fully accessible
Allows users to authenticate with HTTP Form Based authentication
Configure logout with redirect to homepage
*/
#Configuration
public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/img/**", "/js/**", "/index.html", "/").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/index.html")
.permitAll();
}
}
}
I know it is a question from some time ago but I still want to share the answer for people who are struggling with this issue.
After a lot of searching I found out that the /error endpoint in spring boot 2.x is now secured by default. What I mean to say is in the past the /error was a endpoint what had no security at all (or didn't exist). The solution to this issue is quite straight forward.
antMatchers('/error').permitAll()
within your web security adapter configuration(s).
What happens if you don't do this, the security will check the endpoint against your configuration and if it cannot find this endpoint (/error) it will redirect to the standard login form, hence the 302.

How can I configure Spring to use the browser popup for authentication?

I have implemented custom security by extending WebSecurityConfigurerAdapter as below:
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
// Specify the authentication mechanisms that will allow user access to the site.
#Autowired
public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.inMemoryAuthentication()
.withUser("user").password("password").roles("ROLES_USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic()
.and()
.requiresChannel().anyRequest().requiresSecure();
}
}
As per many of the examples. However, when implemented in this way, I am thrown to a login page generated by Spring. I have found plenty of docs that detail how I can override this login page and provde a .html file of my own design, however, all I am really looking to do is supply credentials through the browser authentication popup.
My question is whether I can use the browser popup authentication to authenticate as per my code above (my actual code uses Kerberos in AuthenticationManagerBuilder but same general issue), and if I cannot, can some explain whether the browser authentication popup is reserved for a specific type of authentication or what exactly triggers it to pop up?
Remove:
.and()
.formLogin()
from you configuration, then .httpBasic() will do the basic authentication with the browser popup

Resources