Spring Data REST Keycloak - Best way to secure REST endpoints? - spring

When securing a Spring Data REST application with keycloak the spring security allows to secure REST endpoints by making a configuration class extending KeycloakWebSecurityConfigurerAdapter and overriding configure(HttpSecurity) as follows:
#Configuration
#EnableWebSecurity
#ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/customers/**").hasRole("view-customers")
.antMatchers(HttpMethod.POST, "/customers/**").hasRole("create-customers")
.antMatchers(HttpMethod.PATCH, "/customers/**").hasRole("edit-customers")
.anyRequest().authenticated();
}
}
But hard coding it like this makes difficult for future changes. Is there a better way to do this?

Related

Spring Boot AntMatchers vs #PostAuthorize usage

I'm tasked with implementing RBAC(Role-Based Access Control) in the REST API I'm working on.
What puzzles me is that when I use in my Security class that extends WebSecurityConfigurerAdapter, in configure method antMatchers, the Authorisation is working correctly, but when I dispose of antMatchers and try to replace them by #PostAuthorize on top of an endpoint, RBAC fails to work.
That's my configure method from a class extending WebSecurityConfigurerAdapter:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.rememberMe()
.and()
.addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager()))
.addFilterAfter(new JwtTokenVerifierFilter(), JwtUsernameAndPasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/h2-console/**").permitAll()
.antMatchers("/user").authenticated()
.antMatchers("/hello").hasRole(ApplicationUserRole.ADMIN.name())
.anyRequest()
.authenticated();
http.headers().frameOptions().disable();/*REQUIRED FOR H2-CONSOLE*/
}
Which works fine.
Thats by annotarion on top of an endpoint that shoud be authorized, but is not.
#PostAuthorize("hasRole('ADMIN')")
#RequestMapping("/hello")
String hello(){
return "hello";
}
What am I doing wrong, that it is not workind correctly?
Did you try annotating your security config class with the below annotations?
Something like this.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(final HttpSecurity http) throws Exception {}
}

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

How do you include Spring Boot Actuator with SB 2.1 and not have all endpoints locked under security

I literally can't figure this out and have been through a dozen answers and none of them work. What exactly is the configuration to stop the redirect to login? I'd prefer to leave my actuator endpoints behind security but I honestly don't care either way at this point because I need this application to be usable.
There’s an example of the configuration that is required in Spring Boot’s reference documentation:
#Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint())
.authorizeRequests()
.anyRequest().permitAll();
}
}
Security configuration for a Spring Webflux service to allow access to actuator endpoints:
#Configuration
public class SecurityConfig {
#Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange()
// .pathMatchers("/actuator/**").permitAll()
.anyExchange().permitAll()
.and().csrf().disable().build();
}
}

Adding spring security to Zuul service in spring boot micro service

I am new to micro service architecture.
We have few services like zuul service (api gateway), security service (connect to db check access) and xyz service.
I would like to know, how we can add spring security to the routes defined in the zuul service. ?
On defining authorizeRequests like below on zuul service, it should call security service internally and authenticate the requests.
Example:
.authorizeRequests()
.antMatchers("/user/count").permitAll()
.antMatchers("/user/**").authenticated()
Note: /user End point is defined in the security service.
Please help me with this.
Our Zuul proxy is supporting OAuth2 security. An example of the security config is this:
#Configuration
#EnableResourceServer
public class JwtSecurityConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.antMatchers("/**").hasAuthority("ROLE_API_ACCESS")
.and()
.csrf().disable();
}
}
I would assume if you are doing basic auth you could do something similar using the appropriate class. Maybe something like this.
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
BasicAuthenticationEntryPoint authenticationEntryPoint = new BasicAuthenticationEntryPoint();
authenticationEntryPoint
.setRealmName("EnterpriseDeviceAuthentication");
http
.authorizeRequests()
.antMatchers("/health").permitAll() // allow access to health page
.antMatchers("/somepath").permitAll()
.antMatchers("/somepath2").permitAll()
.antMatchers("/bootstrap.min.css").permitAll()
.anyRequest().hasAnyAuthority(SecurityRoles.ALL_SECURITY_ROLES)
.and().httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf().disable();
}
}

Resources