[java] Difference between Role and GrantedAuthority in Spring Security

There are concepts and implementations in Spring Security, such as the GrantedAuthority interface to get an authority to authorize/control an access.

I would like that to permissible operations, such as createSubUsers, or deleteAccounts, which I would allow to an admin (with role ROLE_ADMIN).

I am getting confused as the tutorials/demos I see online. I try to connect what I read, but I think we treat the two interchangeably.

I see hasRole consuming a GrantedAuthority string? I most definitely am doing it wrong in understanding. What are these conceptually in Spring Security?

How do I store the role of a user, separate from the authorities for that role?

I'm also looking at the org.springframework.security.core.userdetails.UserDetails interface which is used in the authentication-provider referenced DAO, which consumes a User (note last GrantedAuthority):

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)

Or is there any other way to differentiate the other two? Or is it not supported and we have to make our own?

This question is related to java spring spring-mvc spring-security

The answer is


Another way to understand the relationship between these concepts is to interpret a ROLE as a container of Authorities.

Authorities are fine-grained permissions targeting a specific action coupled sometimes with specific data scope or context. For instance, Read, Write, Manage, can represent various levels of permissions to a given scope of information.

Also, authorities are enforced deep in the processing flow of a request while ROLE are filtered by request filter way before reaching the Controller. Best practices prescribe implementing the authorities enforcement past the Controller in the business layer.

On the other hand, ROLES are coarse grained representation of an set of permissions. A ROLE_READER would only have Read or View authority while a ROLE_EDITOR would have both Read and Write. Roles are mainly used for a first screening at the outskirt of the request processing such as http. ... .antMatcher(...).hasRole(ROLE_MANAGER)

The Authorities being enforced deep in the request's process flow allows a finer grained application of the permission. For instance, a user may have Read Write permission to first level a resource but only Read to a sub-resource. Having a ROLE_READER would restrain his right to edit the first level resource as he needs the Write permission to edit this resource but a @PreAuthorize interceptor could block his tentative to edit the sub-resource.

Jake


Like others have mentioned, I think of roles as containers for more granular permissions.

Although I found the Hierarchy Role implementation to be lacking fine control of these granular permission.
So I created a library to manage the relationships and inject the permissions as granted authorities in the security context.

I may have a set of permissions in the app, something like CREATE, READ, UPDATE, DELETE, that are then associated with the user's Role.

Or more specific permissions like READ_POST, READ_PUBLISHED_POST, CREATE_POST, PUBLISH_POST

These permissions are relatively static, but the relationship of roles to them may be dynamic.

Example -

@Autowired 
RolePermissionsRepository repository;

public void setup(){
  String roleName = "ROLE_ADMIN";
  List<String> permissions = new ArrayList<String>();
  permissions.add("CREATE");
  permissions.add("READ");
  permissions.add("UPDATE");
  permissions.add("DELETE");
  repository.save(new RolePermissions(roleName, permissions));
}

You may create APIs to manage the relationship of these permissions to a role.

I don't want to copy/paste another answer, so here's the link to a more complete explanation on SO.
https://stackoverflow.com/a/60251931/1308685

To re-use my implementation, I created a repo. Please feel free to contribute!
https://github.com/savantly-net/spring-role-permissions


AFAIK GrantedAuthority and roles are same in spring security. GrantedAuthority's getAuthority() string is the role (as per default implementation SimpleGrantedAuthority).

For your case may be you can use Hierarchical Roles

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
        class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_ADMIN > ROLE_createSubUsers
            ROLE_ADMIN > ROLE_deleteAccounts 
            ROLE_USER > ROLE_viewAccounts
        </value>
    </property>
</bean>

Not the exact sol you looking for, but hope it helps

Edit: Reply to your comment

Role is like a permission in spring-security. using intercept-url with hasRole provides a very fine grained control of what operation is allowed for which role/permission.

The way we handle in our application is, we define permission (i.e. role) for each operation (or rest url) for e.g. view_account, delete_account, add_account etc. Then we create logical profiles for each user like admin, guest_user, normal_user. The profiles are just logical grouping of permissions, independent of spring-security. When a new user is added, a profile is assigned to it (having all permissible permissions). Now when ever user try to perform some action, permission/role for that action is checked against user grantedAuthorities.

Also the defaultn RoleVoter uses prefix ROLE_, so any authority starting with ROLE_ is considered as role, you can change this default behavior by using a custom RolePrefix in role voter and using it in spring security.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to spring

Are all Spring Framework Java Configuration injection examples buggy? Two Page Login with Spring Security 3.2.x Access blocked by CORS policy: Response to preflight request doesn't pass access control check Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Spring Data JPA findOne() change to Optional how to use this? After Spring Boot 2.0 migration: jdbcUrl is required with driverClassName The type WebMvcConfigurerAdapter is deprecated No converter found capable of converting from type to type

Examples related to spring-mvc

Two Page Login with Spring Security 3.2.x ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Spring 5.0.3 RequestRejectedException: The request was rejected because the URL was not normalized The type WebMvcConfigurerAdapter is deprecated RestClientException: Could not extract response. no suitable HttpMessageConverter found Spring boot: Unable to start embedded Tomcat servlet container UnsatisfiedDependencyException: Error creating bean with name 8080 port already taken issue when trying to redeploy project from Spring Tool Suite IDE Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed Difference between the annotations @GetMapping and @RequestMapping(method = RequestMethod.GET)

Examples related to spring-security

Two Page Login with Spring Security 3.2.x Spring 5.0.3 RequestRejectedException: The request was rejected because the URL was not normalized Unsupported Media Type in postman How Spring Security Filter Chain works Spring security CORS Filter How to configure CORS in a Spring Boot + Spring Security application? Failed to load ApplicationContext (with annotation) disabling spring security in spring boot app When to use Spring Security`s antMatcher()? How to manage exceptions thrown in filters in Spring?