Hamid Mohayeji
Hamid Mohayeji

Reputation: 4295

Spring Security hasRole() for Unauthenticated Users, Considering Role Hierarchy

I have a role hierarchy in my Spring Boot 2 + Spring Security application:

@Bean
public RoleHierarchy roleHierarchy() {
    var rh = new RoleHierarchyImpl();
    rh.setHierarchy("ROLE_ADMIN > ROLE_USER and ...");

    return rh;
}

Now I (as an admin) want to create an entity on behalf of another user, but I should check if that user has a certain authority based on the above hierarchy.

I know that it's possible to call spring security hasRole() for the current authenticated user, but in my case, the user I want to authorize is not authenticated.

Now, I can check to see if the user has that specific authority:

public boolean hasAuthority(User user, String authority) {
    return user.getAuthorities()
            .stream()
            .anyMatch(grantedAuthority -> grantedAuthority.getName().equals(authority));
}

But this way the hierarchy, which is fairly long, would be ignored.

I would be thankful for any help.

Upvotes: 2

Views: 668

Answers (1)

dur
dur

Reputation: 17009

You could use the role hierarchy, see RoleHierarchy#getReachableGrantedAuthorities:

Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(Collection<? extends GrantedAuthority> authorities) 

Returns an array of all reachable authorities.

Reachable authorities are the directly assigned authorities plus all authorities that are (transitively) reachable from them in the role hierarchy.

Example: Role hierarchy: ROLE_A > ROLE_B and ROLE_B > ROLE_C.
Directly assigned authority: ROLE_A.
Reachable authorities: ROLE_A, ROLE_B, ROLE_C.

Parameters:

authorities - List of the directly assigned authorities.

Returns:

List of all reachable authorities given the assigned authorities.

Your modified code:

public boolean hasAuthority(User user, String authority) {
    return roleHierarchy()
        .getReachableGrantedAuthorities(user.getAuthorities())
        .stream()
        .anyMatch(grantedAuthority -> grantedAuthority.getName().equals(authority));
}

Upvotes: 3

Related Questions