It seems that you are conflating between RBAC and DAC (Discretionary Access Control): Deny Access is not typically employed in RBAC, but rather it comes from the DAC world. F.e. its common to see an NTFS ACL (Access Control List) with DENY in it.
You might be trying to implement a merged model (see the example in my response here) - e.g. building an ACL with ACEs (Access Control Entry) pointing to roles. E.g. using groups to grant access to folders...
There are two possible solutions you can use, perhaps even mix'n'match, depends on what makes sense for your system (I've built and used both, in different contexts):
- Ordered ACL - i.e. the ACL is not a big pile of ACEs, but they're in a specific order: higher on the list takes precedence, keep evaluating ACE until you find either a PERMIT ACE, or a DENY ACE for that user. Whichever is first on the list, wins.
- DENY ACE overrides all other ACEs. I.e., if the user is granted access via Role1, scan the ACL for any DENY that applies to the user, and then Role2 would block access no matter what.
Note that you might not be implementing this with a standard ACL model, but truly only checking the user roles - that's still fine, the above still applies (just harder to visualize and explain).
The real question you need to figure out is, What makes sense for your system? Are you trying to implement SoD (Segregation/Separation of Duties)? If so, it's clear that DENY must override any PERMIT. If you want the user to configure this (in which case its DAC, not RBAC), the first option gives the most flexibility, since there IS a way to work around it.