ZfcRbac Role Provider and Identity getRoles() - zend-framework2

I couldn't understand a concept when using ZfcRbac.
1. I use my own User entity with implementing ZfcRbac\Identity\IdentityInterface
2. This interface has addRole and getRoles methods and getRoles() should return array of Rbac\Role\RoleInterface so I have an array of Rbac\Role\RoleInterface
3. I get roles from my custom model and add roles to User entity via addRole() when authenticating the user
4. Rbac\Role\RoleInterface has hasPermission() method which returns role's permissions
Summary:
After authentication I have my authenticated User identity information, roles and permissions for per role. Why I need another RoleProvider and list my all roles in it? What am i missing?

As you can see in the php doc in the IdentityInterface The getRoles() method can return two things:
1. an array of strings
2. an array of Rbac\Role\RoleInterface
In case you return an array of strings you need an additional RoleProvider to "translate" the strings to actual instances of a Rbac\Role\RoleInterface. If you return an array of Rbac\Role\RoleInterface it seems to me that you do not longer need a RoleProvider.

It seems to me that Role Providers are not for generating a user role list, but rather to the load and build an accessible listing of application roles with permissions to be used during and in the authorization service.
So I am extending the Zend\Authentication\AuthenticationService so I can implement the abstract method getRoles() of the ZfcRbac\Identity\IdentityInterface.
I still need to code for the accessing of user roles and storage of user roles to be authorized. There are not many examples of loading user roles using the AuthenticationService or IdentityInterface, and the loading of the role provider seems well documented. I am trying to decouple Authentication from Authorization. I Authenticate and then I load the user's role in my Authorization module because I may have cases where authentication is all that is necessary and the loading of a guest role is overhead.

Related

Best Practices for Roles vs. Claims in ASP.NET Identity

I am completely new to the use of claims in ASP.NETIdentity and want to get an idea of best practices in the use of Roles and/or Claims.
After all this reading, I still have questions like...
Q: Do we no longer use Roles?
Q: If so, why are Roles still offered?
Q: Should we only use Claims?
Q: Should we use Roles & Claims together?
My initial thought is that we "should" use them together. I see Claims as sub-categories to the Roles they support.
FOR EXAMPLE:
Role: Accounting
Claims: CanUpdateLedger, CanOnlyReadLedger, CanDeleteFromLedger
Q: Are they intended to be mutually exclusive?
Q: Or is it better to go Claims ONLY and "fully-qualify" you claims?
Q: So what are the best practices here?
EXAMPLE: Using Roles & Claims Together
Of course, you would have to write your own Attribute logic for this...
[Authorize(Roles="Accounting")]
[ClaimAuthorize(Permission="CanUpdateLedger")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here
return View();
}
EXAMPLE: Fully-Qualifying Your Claims
[ClaimAuthorize(Permission="Accounting.Ledger.CanUpdate")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here
return View();
}
A role is a symbolic category that collects together users who share the same levels of security privileges. Role-based authorization requires first identifying the user, then ascertaining the roles to which the user is assigned, and finally comparing those roles to the roles that are authorized to access a resource.
In contrast, a claim is not group based, rather it is identity based.
from Microsoft documentation:
When an identity is created it may be assigned one or more claims issued by a trusted party. A claim is a name value pair that represents what the subject is, not what the subject can do.
A security check can later determine the right to access a resource based on the value of one or more claims.
You can use both in concert, or use one type in some situations and the other in other situations. It mostly depends on the inter-operation with other systems and your management strategy. For example, it might be easier for a manager to manage a list of users assigned to a role than it is to manage who has a specific Claim assigned. Claims can be very useful in a RESTful scenario where you can assign a claim to a client, and the client can then present the claim for authorization rather than passing the Username and Password for every request.
As #Claies perfectly explained, claims could be a more descriptive and is a deep kind of role. I think about them as your role's ids. I have a gym Id, so I belong to the members role. I am also in the kickboxing lessons, so I have a kickboxing Id claim for them. My application would need the declaration of a new role to fit my membership rights. Instead, I have ids for each group class that I belong to, instead of lots of new membership types. That is why claims fit better for me.
There is a a great explanation video of Barry Dorrans, talking about the advantage of using claims over roles. He also states that roles, are still in .NET for backward compatibility. The video is very informative about the way claims, roles, policies, authorization and authentication works.
Or check a related session shared by Lafi
Having used various authentication and authorisation techniques over decades, my current MVC application uses the following methodology.
Claims are used for all authorisation. Users are assigned one role (multiple roles are possible but I do not need this) - more below.
As is common practice, A ClaimsAuthorize attribute class is used. Since most controller actions are CRUD, I have a routine in the code-first database generation that iterates all controller actions and creates claim types for each controller action attribute of Read/Edit/Create/Delete. E.g. from,
[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]
For use at in an MVC View, a base controller class presents view bag items
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user claims
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();
// set Viewbag with default authorisations on this controller
ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
}
base.OnActionExecuting(filterContext);
}
For website menus and other non-controller actions, I have other claims. E.g. whether a user can view a particular monetary field.
bool UserHasSpecificClaim(string claimType, string claimValue)
{
// get user claims
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get the specific claim if any
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}
return false;
}
public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}
So where do Roles fit in?
I have a table that links a Role to a (default) set of claims. When setting user authorisation, the default is to give the user the claims of their role. Each user can have more or less claims than the default. To make editing simple, the claims list is show by controller and actions (in a row), with other claims then listed. Buttons are used with a bit of Javascript to select a set of actions to minimise the "clicking" required to select claims. On Save, the users claims are deleted and all of the selected claims are added. The web application loads claims only once, so any changes must prompt a reload within this static data.
Managers can therefore select which claims are in each role and which claims a user has after setting them to a role and those default claims. The system has only a small number of users so managing this data is straightforward
To understand the difference between Roles and Claims you must face the limitation of roles and feel how claims come over these issues, so let me give you 2 scenarios to recognize the power of claims where role can't resolve these issues :
1- Your site has two modules (pages, service ..etc) the first module for children (under 18 years old) the other for adults (over 18 years old)
your user identity has a birthday claim
You need to create a policy on this claim so the authorization for each module will be given on this value and if the age of the user is over 18 years then he can go to the adult module and not before this age.
Role is Boolean data type you can have or not have the role, it doesn't have multi values.
2- Your site has role user and you want to prevent access of users to make some maintenance without changing the code.
In claims, you can create an UnderConstrain policy that if true the user can't view the page give property authorize for role user.
At the time of writing this answer we were at '.NET 5.0' with '.NET 6.0' just around the corner. And this is my understanding of what I've seen:
Q: Do we no longer use Roles?
Yep, you're not supposed to use Roles any longer (at least not the way you did it in the previous frameworks.
Q: If so, why are Roles still offered?
To make upgrading projects easier/faster?
Q: Should we only use Claims?
yes. But be sure to check out the video posted here in the answer by #Jonathan Ramos.
Q: Should we use Roles & Claims together?
No, but you can put a role into a claim ofcourse, but be sure to upgrade your project to use Claims only.
And you should not have to write you're own attributes, you should use policy for that, as it's the way of the newer framework. If you need you're own attributes you're "doing it wrong", just create your own Requirement(handler) that's what the whole 'new' policy is all about.
In the current framework the attribute ClaimAuthorize is not even available anymore.

Spring Security in Grails providing authorization

A suggestion here would be deeply appreciated.
We use Spring Security domain object security to lock down access to specific objects in our Grails application. We have extended permissions as well. We use normal #PreAuthorize annotation to control access to the domain objects depending up the privileges assigned to a specific user.
In this architecture, I want for one user to be able to invite a second user to join a group. To do this, the second user receives an invitation from the first user to join a group with specific privileges. The second user can choose to accept or reject the invitation.
Given that the domain object belongs to the first user, not the second user, how could I grant access to the second user to the domain object with the privileges offered?
I have tried to hack a solution using #PreAuthorize("permitAll") on a service method just to see if that would work. While not ask secure as granting an object the privilege to set privileges to a domain object, it at least would get me going. But no joy, I continue to get "accessDenied for class" errors, presumably because the current user is the second user, not the domain object owner.
Do I need to work through the SpEL suggestion here? I barely understand how the bean resolver works unfortunately.
Edit: Even when I verify the invitation is valid at invocation Spring ACL throws an exception when the first ACE for the new user is attempted to be inserted. The exception occurs in void setPermissions(ObjectIdentity oid, recipient, Collection permissions) at the insertAce call:
void setPermissions(ObjectIdentity oid, recipient, Collection permissions) {
Sid sid = createSid(recipient)
MutableAcl acl
try {
acl = aclService.readAclById(oid)
}
catch (NotFoundException e) {
acl = aclService.createAcl(oid)
}
int deleted = 0
acl.entries.eachWithIndex { AccessControlEntry ace, int i ->
if (ace.sid == sid) {
acl.deleteAce(i-deleted)
deleted++
}
}
permissions.each {
acl.insertAce(acl.entries.size(), it, sid, true)
}
aclService.updateAcl acl
}
I assume that the access is denied because the current user (who did not exist when the invitation was issued) does not have the rights to set permissions on an object owned by another user.
You can use your Role class not only for generic roles (Admin,User, etc.), but for application specific ones as well. Simply allow the user to create a Role for a resource and then allow their invitees to be granted that role. Spring Security comes with a handy ifAnyGranted() method, which accepts a comma-delimited String of role names. At a resource entry-point simply ensure that a particular role is granted:
class Conversation{
Role role
}
class ConversationController{
def enterConversation(){
// obtain conversation instance
if(!SpringSecurityUtils.ifAnyGranted(conversationInstance.role.authority){response.sendError(401)}
}
}
The answer turned out to be using RunAs. For Grails, I did this as follows:
Create a Role specific for allowing invited users to act as an administrator in order to access a protected object. In Bootstrap, ensure this role is loaded into the SecRole domain:
def invitedRole = SecRole.findByAuthority('ROLE_RUN_AS_INVITED_USER')
if (!invitedRole) {
invitedRole = new SecRole()
invitedRole.authority = "ROLE_RUN_AS_INVITED_USER"
invitedRole.save(failOnError:true, flush:true)
}
Ensure in config.groovy that the role can change the target object:grails.plugins.springsecurity.acl.authority.changeAclDetails = 'ROLE_RUN_AS_INVITED_USER'
Enable RunAs in config.groovy
grails.plugins.springsecurity.useRunAs = true
grails.plugins.springsecurity.runAs.key = [key]
annotate the service method
#PreAuthorize([check that this is indeed an invited user])
#Secured(['ROLE_USER', 'RUN_AS_INVITED_USER'])
and it all works. The trick was to make the ROLE_RUN_AS_INVITED_USER able to change acl's.
Reference:
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/runas.html
http://grails-plugins.github.io/grails-spring-security-acl/docs/manual/guide/2.%20Usage.html#2.5%20Run-As%20Authentication%20Replacement

Spring Security User Roles Per Organization

In my application I have a top level entity called Organization. The relationship between User and Organization is many-to-many.
Because of this I could have the following scenario:
UserA has role ROLE_ADMIN for OrganizationA
UserA has role ROLE_USER for OrganizationB
I need to ensure that when UserA accesses resources for OrganizationB he is not doing it as an ADMIN. So I need an additional check that the user has the correct roles at the organization level. Is there anything built into Spring Security that allows for this? If not, does anyone know what the best way would be to about solving this?
UPDATE: A bit more information...
A User logs in and chooses which org they want to work with. That is stored in the session. Beyond that, URLs are locked down with the Secured annotation. What that means is that if UserA were to log in and select OrgA, they should be able to access /admin/user/create however, if they log in and choose OrgB they should not have access to that URL.
The long way is to add additional checks in every method where this matters. So call some service method that says "ok, you're an admin for OrgA but not for OrgB and you're logged in using OrgB, so deny this request".
I'm hoping for a more grails / spring-security way of handling this.
You can probably do this by using a custom AccessDecisionVoter. The vote method will supply you with the "configuration attributes" for the resource (method or URL), which will typically be the required roles, and you can obtain the current user's roles/authorities either directly from the Authentication object, or by reading the current org and selecting the appropriate roles for the user.
I'm assuming that you have some way of differentiating the user's roles, based on the org they've selected.
Essentially, you'd be writing an extended version of the standard RoleVoter, which takes the organization into account.
I think I'm little late here but this is what worked for me:
When an organization 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 = "/org-a")
String orgA(HttpServletRequest request) {
request.getSession().setAttribute("org", "org-a")
Organization org = new Organization("org-a")
reloadRolesForAuthenticatedUser(org)
....
}
private void reloadRolesForAuthenticatedUser(Organization org) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication()
List<String> newRoles = getRoles(auth.getPrincipal().getUsername(), org)
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
}

Spring security #notation for IS_AUTHENTICATED_FULLY?

I am simply trying to allow a user access to a method if they are authenticated, but nothing I am doing seems to work. Is there a way to just check if the user has been authenticated? The following still denies the user even when authenticated... Is there a built in role for an authenticated user?
#RequestMapping("/secure")
#PreAuthorize("hasRole('IS_AUTHENTICATED_FULLY')")
public String secure(ModelMap map){
return("secure");
}
IS_AUTHENTICATED_FULLY is not a role - it is a pre-defined credential (aka 'magic' string) recognized by the AuthenticatedVoter to indicate that you have logged in. This voter also supports anonymous and remember-me login.
Roles are processed by the RoleVoter which recognizes any sting starting with "ROLE_" (prefix is configurable). Thus hasRole('IS_AUTHENTICATED_FULLY') doesn't work because it's not a role. #RolesAllowed("IS_AUTHENTICATED_FULLY") wouldn't work for the same reason.
When using Spring expression language, the correct expression is:
#PreAuthorize("isAuthenticated()")
Alternatively, you can use:
#Secured("IS_AUTHENTICATED_FULLY")
No custom classes are required - both voters are enabled by default.
hasRole('ROLE_USER') is the traditional name for any user who is authenticated. You would typically use ROLE_ANONYMOUS for parts where you don't care if the person is authenticated or not.
(Added later:)
I think you will need to implement a custom AccessDecisionVoter that will always vote ACCESS_GRANTED whenever the parameter authentication has isAuthenticated() true, and the CONFIG_ATTRIBUTE is ROLE_USER or similar.
There is further discussion of this in this forum discussion, giving details of a web.xml and other config.
In your custom UserDetailService implementation just add the Role "IS_AUTHENTICATED_FULLY" to the User object before it's returned.
This is what I have ended up using:
#PreAuthorize("isAuthenticated()")
this should work:
#PreAuthorize("isFullyAuthenticated()")

asp.net mvc authentication against shibboleth and authorization

Where do I get information about the currently connected user? That is, how does shibboleth pass the information?
Can I set some restrictions on actions using [Authorize] attribute based on data acquired from shibboleth?
Shibboleth publishes user attributes associated with
sessions into HTTP request headers, based on header names defined
in Attribute Acceptance Policy (1.3.x) or Attribute Mapping (2.x)
files. These headers are transformed into CGI variables based
on mapping rules defined by the CGI specification.
You should be aware of this security advisory:
http://shibboleth.net/community/advisories/secadv_20090615.txt
I have never user shibboleth, but you can get information about the user from Controller.User property. It will return a generic principal of current thread. Using this principal you can check whether the user is authenticated and get a login name of the user. This is due to the reason that after logon an authentication cookie is set and this cookie contains limited amount of information. And on each request after logon only this cookie is checked (if it exists and valid - user is authenticated).
So if you need in some specific information you can manually load a user (it's better to use cache here) and check whatever you want.
Also you can create and attach your own principal with necessary information to the thread on start of a request (e.g. on start of a request load the user from db/cache using user name from base principal, create and set your own principal to thread). After this you can check all properties of the user you need.
Where would you attach your own principal? You say on the start of the request but what if you don't want every request authorizing?
You'll want to create a method in Global.asax.cs that has the following signature
protected void Application_PostAuthenticateRequest()
{
//Your code here.
}
This will be called automatically before almost anything else is done (MVC will call this method if it exists, you don't have to "turn it on" anywhere), and this is where you need to set the Principal. For instance, let's assume you have a header called RolesHeader that has a comma separated value of roles and another header called UserId that has (duh) the user ID.
Your code, without any error handling, might look something like:
protected void Application_PostAuthenticateRequest()
{
var rolesheader = Context.Request.Headers["RolesHeader"];
var userId = Context.Request.Headers["UserId"];
var roles = rolesheader.Split(',');
var principal = new GenericPrincipal(new GenericIdentity(userId), roles);
Context.User = principal;
}
It's the Principal/Identity that the [Authorize] attribute uses, so setting it here at the beginning of the request lifecycle means the [Authorize] attribute will work correctly.
The rest of this is optional, but I recommend it:
I like to create my own custom classes that implement IPrincipal and IIdentity instead of using the GenericPrincipal and GenericIdentity, so I can stuff more user information in it. My custom Principal and Identity objects then have much more rich information, such as branch numbers or email addresses or whatever.
Then, I create a Controller called BaseController that has the following
protected new CustomPrincipal User
{
get
{
return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
}
}
This allows me to access all my rich, custom Principal data instead of just what's defined in IPrincipal. All of my real controllers then inherit from BaseController instead of directly from Controller.
Obviously, when using a custom Principal like this, in the Application_PostAuthenticateRequest() method, you'd set the Context.User to be your CustomPrincipal instead of a GenericPrincipal.

Resources