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

53k views Asked by At

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();
}
5

There are 5 answers

3
Claies On BEST ANSWER

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.

3
Jonathan Ramos On

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

3
AudioBubble On

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

0
SuperDre On

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.

0
mohammed rashed On

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.