10

I want to know if its possible to set roles based on a selected category. In our app there are categories which contain articles. Now we have a role hierarchy like this: ROLE_ADMIN > ROLE_EDITOR > ROLE_USER. The problem is that a user might have different roles based on the currently selected category:

user1 - cat1 - ROLE_USER

user1 - cat2 - ROLE_EDITOR

The categories are not static. New ones can be added and older deleted. Is it possible to achieve this using Spring Security?

GOPI
  • 1,042
  • 8
  • 30
Stefan
  • 12,108
  • 5
  • 47
  • 66

4 Answers4

12

From your description, it sounds like the RBAC model that Spring Security gives you is not enough. You have 2 options available to you. Either:

  1. you customize Spring Security by implement your own Access Decision Manager (see here for details) or
  2. you move to attribute-based access control (aka ABAC as explained by NIST here). The way to use ABAC in Spring is to use a Java implementation of XACML, the eXtensible Access Control Markup Language. XACML gives you an externalized, policy and attribute-based authorization framework. This means you can define policies such as a user with the role=manager can do action=view in the category=foo. You can have as many rules as you like and combine / factor them accordingly.

There are several open-source and vendor implementations of XACML for Java:

  • SunXACML
  • HerasAF
  • IBM
  • Axiomatics (disclaimer: the vendor I work for)

If you want more information on XACML, I would recommend you check out its wikipedia page as well as our YouTube channel that has vendor-neutral tutorials.

XACML might turn out to be too much for your use case but it is still worth considering.

David Brossard
  • 13,584
  • 6
  • 55
  • 88
1

I think I'm little late here but this is what worked for me:

When a new category is selected, you can set a new Authentication object with new roles in your session(The previous authentication object gets invalidated). Something like this:

@RequestMapping(value = "/cat1")
String cat1(HttpServletRequest request) {
    reloadRolesForAuthenticatedUser("cat1")
    ....
}

private void reloadRolesForAuthenticatedUser(String cat) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication()
    List<String> newRoles = getRoles(auth.getPrincipal().getUsername(), cat)
    List<GrantedAuthority> authorities = getAuthorities(newRoles)
    Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(),auth.getCredentials(),authorities)
    SecurityContextHolder.getContext().setAuthentication(newAuth)
}


private List<GrantedAuthority> getAuthorities(List<String> roles) {
    List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>()
    if (!roles.isEmpty()) {
        for (String r : roles) {
            auths.add(new SimpleGrantedAuthority(r))
        }
    }
    return auths
}
Rodrigo Villalba Zayas
  • 5,326
  • 2
  • 23
  • 36
0

I don't know how your "categories" work, but you can set a "ROLE" to UserDetails object.

The UserDetails object has Collection<? extends GrantedAuthority> getAuthorities(); method and "ROLE" is value of GrantedAuthority.getAuthority().

So you can set multiple "ROLE"s to single session.

And You can control your UserDetails object by implement UserDetailsService.

MinGyoo Jung
  • 269
  • 2
  • 6
-1

This use case cannot be done using the default role based access control (RBAC) functionality, as the user permissions are changing dynamically at runtime depending on some data associated to the user.

This is actually the use case for which Access Control Lists (ACLs) where designed for.

Spring security has support for ACLs by adding the spring-acl jar. This is a quote from the spring security manual Acl section:

Complex applications often will find the need to define access permissions not simply at a web request or method invocation level. Instead, security decisions need to comprise both who (Authentication), where (MethodInvocation) and what (SomeDomainObject). In other words, authorization decisions also need to consider the actual domain object instance subject of a method invocation.

See the spring security manual section 16.1 for the details on how Spring security ACLs work. This is a tutorial on how to use Spring security ACLs.

But Spring ACLs imply 4 extra database tables, etc. so if this is a one only case in your application, it is probably better be to create a custom decision manager with some harcoded rules.

But if this use case is frequent in your application you should consider switching to ACLs instead of RBAC, hope this helps.

Angular University
  • 42,341
  • 15
  • 74
  • 81