Expected Behavior
HttpSecurity's authorizeHttpRequests() uses role hierarchy defined as a bean or defined as a separate method like setRoleHierarchy(RoleHierarchy rh) {...}
so the flow will be like
@Bean
public SecurityFilterChain filterChain(@NotNull HttpSecurity http) {
...
http.authorizeHttpRequests()
.setRoleHierarchy(getRoleHierarchy())
.requestMatchers("my.site/admin")
.hasRole("ADMIN")
...
}
Current Behavior
HttpSecurity's authorizeHttpRequests() uses role hierarchy by .access() method using redefined AuthorityAuthorizationManager<RequestAuthorizationContext>. it is quite inconvenient and quite a lot of code.
so i need to do
@Bean
public AuthorityAuthorizationManager<RequestAuthorizationContext> adminAuthorityAuthorizationManager() {
AuthorityAuthorizationManager<RequestAuthorizationContext> objectAuthorityAuthorizationManager = AuthorityAuthorizationManager.hasAuthority("ROLE_ADMIN");
objectAuthorityAuthorizationManager.setRoleHierarchy(getRoleHierarchy());
return objectAuthorityAuthorizationManager;
}
and then use this
http.authorizeHttpRequests()
.requestMatchers("my.site/admin")
.access(adminAuthorityAuthorizationManager())
Context
i found that AuthorityAuthorizationManager has a non-static RoleHierarchy field.
well, i propose:
1) make a private static RoleHierarchy field in AuthorizeHttpRequestsConfigurer.AuthorizedUrl defaulted to NullRoleHierarchy
2) set it by a static method setRoleHierarchy()
3) pass it to hasRole... methods under-the-hood
4) pass it to hasRole... methods of AuthorityAuthorizationManager in 3)
5) set it to inner field roleHierarchy (!)
6) continue as it is now
so, we will have an easy setter for roleHierarchy without clumsy use of redefined classes for each custom role
Comment From: evgeniycheban
Hi, @esselesse, I think what you are looking for is already implemented, the RoleHierarchy can be defined as a @Bean and propagated to AuthorityAuthorizationManager, here is an example of how it can be achieved:
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests((requests) -> requests
.anyRequest().hasRole("USER")
)
.build();
}
@Bean
RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
return roleHierarchy;
}
This was added in https://github.com/spring-projects/spring-security/issues/12473, so you may need to consider updating Spring Security version in your project.
@jzheaux Could you please remind in which release it was included?
Comment From: esselesse
@evgeniycheban if i use these plugins in build.gradle:
id 'org.springframework.boot' version '3.0.6'
id 'io.spring.dependency-management' version '1.1.0'
(that are latest versions of plugins at this momentum)
and use
implementation 'org.springframework.boot:spring-boot-starter-security'
in the body of dependencies - well, it is not working.
i assume that maybe something wrong in versions, cuz the problem seems exactly the same as You mentioned (https://github.com/spring-projects/spring-security/issues/12473). should i use explicit version of spring security?
------- my problem is below this line, just as example ----------
i do this:
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy(
"ROLE_ADMIN"
+ " > "
+ "ROLE_USER"
+ " > "
+ "ROLE_GUEST");
return hierarchy;
}
and in filterchain
http.authorizeHttpRequests()
.requestMatchers(ADMIN_URL_PATTERN, API_URL_PATTERN, MAILING_URL_PATTERN)
.hasRole("GUEST")
.anyRequest()
.authenticated();
when i try to access any URL matches ADMIN_URL_PATTERN using a client with ROLE_USER role, i get 403 error (access denied).
but if i change "GUEST" to "USER" - everything fine.
Comment From: jzheaux
This feature was released in 6.1.0-M1 and subsequently 6.1.0. If you update to Spring Boot 3.1.0 once it is out, then this dependency will be managed for you. Until then, yes, you can manage Spring Security up to 6.1.0 in your pom.
Can you try using Spring Security 6.1.0 and see if this works for you?
Comment From: esselesse
tried out boot 3.1.0. it's amazing! works!
thank You!
Comment From: jzheaux
Glad the latest is working for you, @esselesse! I'll close this in favor of https://github.com/spring-projects/spring-security/pull/12505, then.