Springboot hasAnyRole allow all/any roles - spring

I have an endpoint that I have to expose to all roles, whoever has at least one of the roles should get access to the api.
#PreAuthorize("hasAnyRole('ADMIN', 'USER')")
Now that the number of roles is increasing i have to add all the new roles to the API. Is there any way to expose everyone who have any role without specifying everyrole here?
I am expecting something like this
#PreAuthorize("hasAnyValidRole()")

We can directly do it from WebSecurityConfigurerAdapter, override the method protected void configure(HttpSecurity http) and don't use PreAuthorize annotation
you may simple write
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("your end point here").authorizeRequests().anyRequest().authenticated();
}
}
this will allow any authenticated user to access that URL
Hope this Helps !

Finally got a quite easy solution.
#PreAuthorize("isAuthenticated()")

Related

Spring Security add/remove antMatchers and roles dynamically at runtime

Is there a way to change this place dynamically? In other words, invoke the method that adds or removes antMatchers or override completely. map roles, etc.
#EnableWebSecurity
public class WebSecurityConfigAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
//Change this configs dynamically at runtime
}
}
In Spring Security version 5.6, which is in 5.6.0.M3 as of now, you can create an AuthorizationManager bean and define place your rules anywhere you want, like so:
#Autowired
private MyCustomAuthorizationManager access;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().access(access);
}
Or even better, you can define a SecurityFilterChain bean and make use of method parameter injection, instead of extending WebSecurityConfigurerAdapter:
#Bean
SecurityFilterChain app(HttpSecurity http, MyCustomAuthorizationManager access) throws Exception {
...
http.authorizeRequests().access(access);
...
return http.build();
}
There is a great presentation showing how to do this.
I ended up with this solution. The solution is to close the current context and run the new one. Of course, it has the disadvantage because it causes downtime but I use a load balancer and several nodes so it's was ok for me.

hasRole() and denyAll() method don't restrict access to resources

I'm developing Spring Boot and Spring Security web application with authorization and resource servers enabled. I have defined a set of users with roles assigned to them and trying to implement roles based access to REST endpoints. I was able to implement token based access to endpoints, but can't restrict access to end users, that would be based on their roles.
I have done two endpoints: /rest/products/list and /rest/products/add and trying to restrict access to /rest/products/add endpoint with the user that is of ADMIN role.
My WebSecurityConfigurerAdapter is as follows:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.passwordEncoder(passwordEncoder)
.withUser("user1")
.password(passwordEncoder.encode("user1Pass"))
.roles("USER")
.and()
.withUser("user2")
.password(passwordEncoder.encode("user2Pass"))
.roles("USER")
.and()
.withUser("admin")
.password(passwordEncoder.encode("adminPass"))
.roles("ADMIN");
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/rest/products/add").hasAnyRole("ADMIN")
.antMatchers("/rest/products/list").denyAll();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Therefore, resource /rest/products/add should be accessible to admin / adminPass user only as far as that user has ADMIN role. But if to try to it with user1 / user1Pass, it is still accessible:
Get access token for user1 postman screen
Accessing ADMIN only related endpoint with user1 Postman screen
Also I added (in the testing purpose) in the configuration method the following rule .antMatchers("/products/list").denyAll(); Here is indicated that /products/list shouldn't be accessible to any user. But it still keeps on responding (provided access correct token).
In the similar question here How to fix role in Spring Security? the order of matchers should be from the more specific to the less. But in my case there are two matchers and no matchers that can overlap them.
I'm using Spring Boot with spring-boot-starter-security plugin version 2.5.2.
What additional configuration should be done to make .hasRole("ADMIN") and .denyAll() work as expected?
Finally was able to find the solution with the following:
Here there is an example of ResourceServerConfigurerAdapter class. From this and from your comment, dur, I realized that I confused ResourceServerConfigurerAdapter and WebSecurityConfigurerAdapter, trying to define access restriction matchers in WebSecurityConfigurerAdapter. I changed resource server configuration in the following way:
Method that was in WebSecurityConfigurerAdapter
#Override
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/rest/products/add").hasAnyRole("ADMIN")
.antMatchers("/rest/products/list").denyAll();
}
was moved to
#Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/rest/products/add").hasAnyRole("ADMIN")
.antMatchers("/rest/products/list").denyAll();
}
}
Now restrictions defined by matchers above are working as expected.

Role based security in spring

I'm having a usecase where I have to restrict users with some role instead of url-pattern to a fixed set of ip addresses. For example: A user with super-admin role can access only from ip-addresses 1.1.1.1, 2.2.2.2 etc.
I have to implement it on both authentication as well as on authorization.
You can do that like below code by adding hasRole and hasIpAddress methods.
#Configuration
#EnableWebSecurity
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('admin') and hasIpAddress('127.0.0.1')")
.antMatchers("/admin/**").access("hasRole('admin') and hasIpAddress('192.168.1.0/24')")
.antMatchers("/admin/**").access("hasRole('admin') and hasIpAddress('0:0:0:0:0:0:0:1')");
}
}
Full post : https://stackoverflow.com/a/44304683/6572971

How to disable csrf in spring security for only localhost?

I have working spring boot application in which csrf is enabled but now I want to disable it only for localhost. any request from other domain must underpass csrf security but for localhost, I want to disable it. how can I achieve that?
I know how to disable it by changing
#Configuration
#EnableWebMvcSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf.disable();
}
}
the above code disabled csrf but I want to disable csrf for the only localhost.
Can you please help me?
EDIT: I know how to do it by two profile. Thanks #daren for your detailed answer.
You could use Spring Profiles to achieve what you are looking to do.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
At it's simplest you could have two configurations
#Configuration
#EnableWebMvcSecurity
#Profile("!deployed") //Not(!) deployed profile
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf.disable();
}
}
And in deployed regions active the deployed profile.
#Configuration
#EnableWebMvcSecurity
#Profile("deployed")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf.enable();
}
}
Depending on what security configuration you are doing you could do the inverse of this and active a local profile by default which would do the disabling.
You can use the CsrfConfigurer#requireCsrfProtectionMatcher method and use a RequestMatcher which checks the request local vs remote address e.g.
private RequestMatcher csrfProtectionMatcher() {
final Set<String> allowedMethods = ImmutableSet.of("GET", "HEAD", "TRACE", "OPTIONS");
return request -> !allowedMethods.contains(request.getMethod()) && !(request.getLocalAddr().equals(request.getRemoteAddr()));
}

Allowing a client application to configure http security from an already wired WebSecurityConfigurerAdapter

I am using spring-boot and spring-security.
I have a generic WebSecurityConfigurerAdapter setup for a number of different projects. The problem is that I want custom Controller security for each project, everything else remains the same. The most obvious solution was to make it Abstract and force each project to extend it but I suspect there is a better way through events or something.
Here is the configure method of WebSecurityConfigurerAdapter
#Override
protected void configure(final HttpSecurity http) throws Exception {
...
http.authorizeRequests()
.antMatchers("/health*").permitAll()
.antMatchers("/endpoints/**").permitAll()
.antMatchers("/rest/open/**").permitAll()
.antMatchers("/login/impersonate*").hasAnyRole("ADMIN", "ADMINISTRATOR")
// AT THIS POINT I WOULD LIKE EACH PROJECT TO OPTIONALLY CONFIGURE http AS THEY WISH
http.authorizeRequests().antMatchers("/**").authenticated();
...
}
Is there a cool way to do this in spring though a bean configuration or something?
#Bean //something like this perhaps????
public void configureSecurity(final HttpSecurity http) {
http.authorizeRequests()
.antMatchers("/rest/admin*").hasAnyRole("ADMIN", "ADMINISTRATOR")
}
you can use multiple WebSecurityConfigurerAdapter classes, juste make sure each of them are in packages scanned by Springboot autoconfiguration.
if a client project want to override existing security constraints, add the #Order annotation:
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE)
public class ClientSecurityConfig extends WebSecurityConfigurerAdapter {
public void configure(HttpSecurity http) {
http.antMatcher("/rest/admin*").authorizeRequests().anyRequest().hasAnyRole("ADMIN", "ADMINISTRATOR");
}
}
Pay attention to the antMatcher() that is before the authorizeRequests(), this is done to limit the scope of the client config. without that, it will erase all of the default config (every URL except /rest/admin* will return 403 Unauthorized).

Resources