How to Setup Spring Cloud Gateway with Keycloak Adapter? - spring

I have setup a spring Cloud Gateway with Auth by keycloak but wanted to add Policy Enforcer of Keycloak for Fine Grained Authorisation. So that Cloud gateway will do the authorisation, and policy enforcement. And each microservies can act as a OAuth2 resource servers.
If its doable using Spring feature then its an added bonus. But a solution with Keycloak adapter is also fine.
UPDATE
Adding my Security Config
#EnableWebFluxSecurity
public class SecurityConfig {
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
http.authorizeExchange()
.anyExchange().authenticated()
.and()
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance());
http.headers().frameOptions().mode(Mode.SAMEORIGIN);
http.csrf().disable();
return http.build();
}
}

Related

How can we change the default Spring Boot login page

We are migrating our legacy application, which runs on a deployed Java application server (Tomcat, Glassfish) to Spring Boot. The legacy application has a login JSP page which defines a form with a action="j_security_check" endpoint, which integrates with the application server's security infrastructure.
In the new application, we have overridden WebSecurityConfigurerAdapter and can successfully use form based authentication against our LDAP server. However, we are presented with the default Spring security login page. How can we configure Spring Boot to use our original login JSP?
Thanks
You need spring mvc not just general spring boot to be able to serve jsp files.
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
// ...
}
Don't forget the
.loginPage("/login").permitAll(); as you want your login page to be open to all users who try to authenticate.
Here is the documentation spring doc custom login page
Also make sure that you have a controller that serves your login_jsp for the path /login

CORS spring security filter vs WebMvcConfigurer.addCorsMappings

What the difference of cors() filter in configure method of WebSecurityConfigurerAdapter class and create bean of WebMvcConfigurer and override addCorsMappings method? when we use of which? can anyone explain it?
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000");
}
};
}
vs
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.csrf().disable()
.authorizeRequests()
.mvcMatchers("/rest/**").authenticated()
.anyRequest().permitAll()
.and()
.oauth2ResourceServer().jwt().jwtAuthenticationConverter(this.jwtAuthenticationConverter())
;
}
}
Spring Web MVC
WebMvcConfigurer is part of the Spring Web MVC library. Configuring CORS with addCorsMappings adds CORS to all URLs which are handled by Spring Web MVC, see 1.7.2. Processing:
Spring MVC HandlerMapping implementations provide built-in support for CORS. After successfully mapping a request to a handler, HandlerMapping implementations check the CORS configuration for the given request and handler and take further actions.
You have to use it, if no Spring Security is used (non secured applications) or not all Spring Web MVC URLs are handled by Spring Security (some ULRs are unsecured).
You can't use it for non Spring Web MVC URLs like JSF, Servlet, JAX-WS, JAX-RS, ...
Spring Security
WebSecurityConfigurerAdapter is part of the Spring Security library. Configuring CORS with cors() adds CORS to all URLs which are handled by Spring Security, see 15.8. CORS:
Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.
The easiest way to ensure that CORS is handled first is to use the CorsFilter.
You have to use it, if you use Spring Security.
If you are using Spring Web MVC and Spring Security together you can share the configuration, see 15.8. CORS:
If you are using Spring MVC’s CORS support, you can omit specifying the CorsConfigurationSource and Spring Security will leverage the CORS configuration provided to Spring MVC.

Protect Actuator endpoints with user/password while granting public access for RestControllers

I updated an already existing application from Spring Boot 1.3 to 2.0.1. This application makes use of the Actuator and exposes a REST-style API.
In Boot 1.3 the API could be used without authentication and the actuator endpoint was configured to be password protected:
security.user.name=foo
security.user.password=bar
security-user.role=ADMIN
I updated this like documented in the configuration changelog and renamed the entries from security.user.name to spring.security.user.name and alike.
But when I try to curl my API, I am denied because I do not provide credentials:
In the Spring Blog I found a possible solution how to configure Spring Security on a detailled level:
http
.authorizeRequests()
// 1
.requestMatchers(EndpointRequest.to("status", "info"))
.permitAll()
// 2
.requestMatchers(EndpointRequest.toAnyEndpoint())
.hasRole("ACTUATOR")
// 3
.requestMatchers(StaticResourceRequest.toCommonLocations())
.permitAll()
// 4
.antMatchers("/**")
.hasRole("USER")
.and()
...
but this is more fine-grained than I need and I am looking for an application.properties based solution.
Is there a way to solve this without additional code ?
When you set spring.security.user.name and spring.security.user.password, you are configuring form login via spring-security for the whole application, including the Actuator endpoints.
Unfortunately, in Spring Boot 2.0 you cannot set a different username/password or disable authentication for the Actuator endpoints using the properties. This means you have to explicitly allow the actuator endpoints through Security configuration.
Through spring-security, you can also allow public access to your endpoints and require credentials for the actuator endpoints very easily:
#Configuration
public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/actuator/**").hasRole("ACTUATOR")
.anyRequest().permitAll();
}
}
(I assumed you were using WebMvc, not WebFlux, which is a bit different)
Verify that you have the following in the application.properties:
spring.security.user.name=user
spring.security.user.password=pass
spring.security.user.roles=ACTUATOR,USER # and others, if you like
management.endpoint.health.roles=ACTUATOR
See here for a quick and nice explanation between the differences in Actuator in Spring 1.x vs 2.0.
For Spring Boot 2.0, when we override the configure method of WebSecurityConfigurerAdapter all existing security backs off and we can provide our custom security. In your case you just need to authenticate the actuator endpoints, which can be done as follows:
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/actuator/**").authenticated();
}
}
No changes are required in the application.properties file.

Spring Boot Security - Open access for / with restricted /admin access?

So i have a simple spring boot app with out-of-the-box security configuration. In my 'dev' profile I've open access to all URLS with these properties
# dev
security.basic.enabled=false
management.security.enabled=false
and I can enable authentication for all URL's in my 'production' profile by changing the values to
# production
security.basic.enabled=true
management.security.enabled=true
The real security requirement for the application is that it has two pages
The '/' index page should be public to all.
The '/admin' page should be restricted.
I know from countless other stackoverflow questions in spring-boot-security and spring-security that I can override the default spring-boot security config by using the #EnableWebSecurity and then defining custom rules
#EnableWebSecurity
public class WebMvcConfig extends WebMvcConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()....
}
I'm wondering is there not a simpler way which configures spring-boot only, and which doesn't involve the customisation of the spring-security to achieve this requirement?
There's a difference between overriding and configuring. By using #EnableWebSecurity, you're still just configuring Spring Security to work the way you want it to work. So to answer your question, no, there is not a "simpler way". This is how you do it and it isn't difficult.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.and()
.authorizeRequests()
.antMatchers("/admin/**").authenticated();
}
}
Something like that is more or less all you need based on your requirements.

Using http-basic-authentication with spring webservices

I followed https://spring.io/guides/gs/producing-web-service/ to implement simple webservice using Spring. Everything works like expected. Now I am trying to add http basic authentication to it using javaconfig. How should I proceed? I found some links where #EnableWebSecurity was used however nothing seems to work... Service responds without authentication...
Just create a Spring Security config file like this:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("ROLE_USER");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
Here's a notice tutorial to follow up: http://www.mkyong.com/spring-security/spring-security-hello-world-annotation-example/
Based on the tags you added to the question I see you are exposing the SOAP service using Spring Boot. In that case just add the spring-boot-starter-security Spring Boot starter project as a dependency. This will include Spring Security and by default ‘basic’ authentication is added on all HTTP endpoints (including your SOAP service).
By default a random password is generated at startup but you can configure your own user name/password using Spring Boot security properties.
If would like more information, I created a blog post which illustrates how to setup Spring WS basic authentication using Spring Boot.

Resources