Using Claims-based Authorization in MVC and Web API

.NET 4.5 ships with a claims-based authorization infrastructure around the ClaimsAuthorizationManager class. I have written about that before, and I am still a fan of that approach (not necessary of the non-existent tooling).

Claims-based authorization encourages you to have a clean separation of business and authorization code – and that’s much better than sprinkling role checks all over your code base.

The problem is, that the corresponding API is not very approachable, especially in the face of “modern” application development like MVC or Web API. The main problem here is that the classes that ship with .NET 4.5 to invoke authorization are based on a code access security permission (ClaimsPrincipalPermission) and calling the CheckAccess method will throw a SecurityException instead of returning a boolean.

This approach typically gets in your way, e.g. ClaimsPrincipalPermission gets invoked directly by the CLR, which means it will also run in unit tests, and unhandled exceptions short-circuit your processing pipeline.

That said, all the base APIs in .NET 4.5 allow using claims-based authorization in a much more sensible way, you just have to write your own plumbing. Since I am working mostly with MVC and Web API these days, I decided to do that.

Thinktecture.IdentityModel contains an authorization filter called ClaimsAuthorizeAttribute (well – strictly speaking two filters – one for Web API, one for MVC) to make the connection to ClaimsAuthorizationManager.

You can either use them as a global authorization filter, e.g.

MVC

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

{

    filters.Add(new HandleErrorAttribute());

    filters.Add(new ClaimsAuthorizeAttribute());

}

Web API

public static void Register(HttpConfiguration config)

{

    config.Routes.MapHttpRoute(

        name: “DefaultApi”,

        routeTemplate: “api/{controller}/{id}”,

        defaults: new { id = RouteParameter.Optional }

    );

 

    // add global authorization filter

    config.Filters.Add(new ClaimsAuthorizeAttribute());

}

 

In that case the registered authorization manager will be invoked for every request with a resource/http method pair (Web API) or a controller/action pair (MVC).

..or you can decorate controllers and actions with it. With that approach you can also pass in explicit resource/operation pairs, e.g.:

[ClaimsAuthorize(“Read”, “SomeData”)]

public string Get()

{

    return “somedata”;

}

You can also pass in multiple resource descriptions, if that makes sense for your authorization logic:

[ClaimsAuthorize(“View”, “StreetAddress”, “TelephoneNumber”)]

public ActionResult Contact()

{

    ViewBag.Message = “Your contact page.”;

 

    return View();

}

…or you can invoke the authorization manager imperatively:

public string Get(int id)

{

    var isAllowed =
      ClaimsAuthorization.CheckAccess(“Get”, “CustomerId”
, id.ToString());

 

    …

}

 

Note: The WIF team made the unfortunate design decision to provide a default implementation of ClaimsAuthorizationManager that always returns true. That means, if you (or your customers) forget to register the authorization manager in configuration, all your access checks will always succeed. And that’s really bad.
Fortunately my ClaimsAuthorization class above (that is also used by the attributes internally) checks that. It will throw an exception when no custom ClaimsAuthorizationManager is configured, so you directly know what’s wrong.

The binaries are on Nuget, and you can find the full sample here.

HTH

This entry was posted in .NET Security, ASP.NET, IdentityModel, WebAPI. Bookmark the permalink.

48 Responses to Using Claims-based Authorization in MVC and Web API

  1. Christian says:

    How would the claims in your last example (var isAllowed =
    ClaimsAuthorization.CheckAccess(“Get”, “CustomerId”, id.ToString());) look like?

    In my understanding I would have created a claim of type “CustomerId” with e.g. the value 5 if the user is allowed to access user 5.

    How would you check the access in the ClaimsAuthorizationManager?
    If I understand your .CheckAccess method correctly it converts all but the first parameters into “ResourceType”.
    Would I check for the resource “CustomerId” and for the resource “5”? (I would have checked for the presence of “CustomerId” and then compared the values.)

    • well – i wouldn’t do it like that – claims describe the identity of a principal. not his authorization data (this may sometimes overlap).

      What claims would you create when the use can access 1 million of your customers??

      In claims based authz you pass in the intent of the user + his identity. The rest is up to the authz manager.

      • Andy Cohen says:

        I’m questioning this paradigm as well.

        Can you provide an example of how you would implement the ClaimsAuthorization Manager for this particular example? Or perhaps fill in the blanks:

        public override bool CheckAccess(AuthorizationContext context)
        {
        if (ClaimsPrincipal.Current.Identity.IsAuthenticated)
        {

        TraceAuthorizationContext(context);

        Claim actionClaim = context.Action.Where(x => x.Type == “http://application/claims/authorization/action”)
        .FirstOrDefault();

        Claim resourceClaim = context.Resource.Where(x => x.Type == “http://application/claims/authorization/resource”)
        .FirstOrDefault();

        IPrincipal principal = context.Principal;

        string resource = resourceClaim.Value;
        string action = actionClaim.Value;

        // NOTE: Add custom logic here
        // DO SOMETHING HERE FOR THE EXAMPLE:
        /*
        var isAllowed =
        ClaimsAuthorization.CheckAccess(“Get”, “CustomerId”, id.ToString());
        */

        return base.CheckAccess(context);
        }

        return false;
        }

      • Well in pseudocode:

        Evaluate if principal with claims x is allowed to do action y on resource z. Ask additional data stores if you have to.

        What’s questionable?

      • Andy Cohen says:

        WordPress only allows the threads to go so deep, so I’m responding here.

        I guess I the word paradigm was a little out of place. My question is, are you going to have a bunch of if then that statements one on top of each other?

        What I am frustrated by is the lack of guidance on what the best practices are in implementing this. I could certainly write a lookup system that checks to see if the principal who is requesting the action and resource in fact does have access based on their claims – but is that the intention? You keep saying “it’s up to you”. Can you elaborate any here?

      • That’s the intention yes.

        Unfortunately there is no “framework” around that.

      • Andy Cohen says:

        All intentions aside, would you recommend this? (I’m assuming so) I was going to read the Appendix G: “Authorization Strategies” referred to in your Patterns and Practices book, but it looks like it was never added to any of the 3 editions that I have read.

        I can certainly implement my own code here, but I hate to do that when it comes to Authentication or Authorization. I tend to want to rely on tried, tested, and true patterns when it comes to security.

      • It seems Microsoft never added that appendix. I remember we discussed it. But it was hard to give general advice.

        The resource/action pattern is a tested one. You just have to implement it yourself.

        Or start an open source project around it, I am happy to review it/give advice.

  2. I just spent the last week taking apart all the System.Security.Principal objects trying to figure out why the hell I was having trouble gathering group roles from AD, and ended up writing a custom filter attribute to use DirectoryServices.AccountManagement… all the while looking at the Identity’s Claims collection and day dreaming that I was using it instead.

    Anyway, I really liked your article. I’ll take a look at the filter soon.

  3. Michael De Marco says:

    Why don’t you provide a useful example of how the claims authorization manager might determine if a claims principal can actually get that customer id. CheckAccess(“Get”, “CustomerId”, id.ToString());). I downloaded the sample code and below is what you have. Bear in mind i understand your leaving it up to us to determine how the CheckAccess call gets implemented. However, there is something to be said about ‘best practices’. What is a best practice for mapping claims to authorization?Should we put the authorization attributes in a table connected to the relying party and then maybe say if the iclaimsprincipal is in a certain role then they are authorized to do A, B, C. I understand that authorization should not be a part of STS as STS is largely communicating identity not authorization. In true architecture there should be a piece of middleware not STS that maps principals to authorizations so that the relying party does not have to assemble this. If I have ten relying parties and I have to do the same things it’s quite duplicative.

    public override bool CheckAccess(AuthorizationContext context)
    {
    Trace.WriteLine(“\n\nClaimsAuthorizationManager\n_______________________\n”);

    Trace.WriteLine(“\nAction:”);
    Trace.WriteLine(” ” + context.Action.First().Value);

    Trace.WriteLine(“\nResources:”);
    foreach (var resource in context.Resource)
    {
    Trace.WriteLine(” ” + resource.Value);
    }

    Trace.WriteLine(“\nClaims:”);
    foreach (var claim in context.Principal.Claims)
    {
    Trace.WriteLine(” ” + claim.Value);
    }

    return true;
    }

  4. I have written about that before – *how* you actually determine if user A is allowed to do operation X on resource Y is up to you.

    This could be based on roles, this could be row level security inside your DB – or something completely different. Sorry can’t help you here.

    • Michael De Marco says:

      Agreed. However, in the future tell the powers to be to create an abstraction that can be implemented to map identities to authorizations and have that reusable across multiple RP’s.

  5. Rune Trusell says:

    Hi Dominick

    I am trying out claims based authorization. My first problem was how to catch the SecurityException that occurs when the AuthorizationManager.CheckAccess method returns false. I simply cannot get it.

    Then I tryed your IdentityModel, and are currently using the attribute way: [ClaimsAuthorize(“SomeAction”, “SomeResource”)]. This works fine for a user with the right permissions. My AuthorizationManager checks the claims and returns true, and the given method is entered. Hwever, when an unaurhorized user logs on, and the AuthorizationManager returns false (which is correct), a logon-popup is shown. How and where should I control this return value?

    I hope it makes sense, I am totally new into this field.

    All the best,
    Rune

    • I assume this is with basic auth and a browser client (that would be good info to include) ?

      Could you please ask the question on the github issue tracker für identitymodel so other can benefit from that?

      thanks!

      • Rune says:

        Hi,

        This was some front-end issues that I was not aware of. In collaboration with my front-end man, we created our own ClaimsAuthorizeAttribute, deriving from your ClaimsAuthorizeAttribute class. This class handles unauthorized requests by creating a response of type MethodNotAllowed. This way we can handle the 404.

  6. Ibraheem says:

    Thanks for the great article. With regards to the comments that refer to how claims should be mapped to authorizations, IMO a nice pattern would be to have roles contain a collection of authorizations. Your claim could be for a role, or for an authorization. As long as the role contains the authorization, it can be considered as being the authorization. Your CheckAccess(authorization) logic can then use the claim whether its for an authorization explicitly, or for a role that contains the authorization.

  7. Pingback: Scope based Authorization in ASP.NET Web API | www.leastprivilege.com

  8. Venu says:

    Hi,
    I really liked the article, thanks for sharing the information. When I run the sample (ClaimBasedAuthorization) for MVC from downloaded code, it prompts for windows authentication on the index page itself. Is there a way I can say ignore some action methods from claims authentication? For example I need to ignore the authentication check on few action methods like “Log on”, “Register” etc and wondering if there is any attribute like IgnoreClaimsAuthorize so that user can access these pages without being prompted for login. Please advise. Thanks!

  9. jonny salmon says:

    Cheers!!! I’m a big fan of leastprivilege. Perhaps you can help me understand stuff not clear to me. Long story made short: I have a legacy web forms app into which I am splicing ‘account/identity’ code from the NET 4.5 VS2013 Web Forms template. I have modified this code to include persisting Claims in the DB and in the ClaimsPrincipal. Here’s my question. If I want to invoke ClaimsAuthorizationManager.CheckAccess(..) at the top of the processing pipeline, then what event in global.asax do I hook to do so? Seems like PostAuthenticateRequest is the answer. In any case, upon determining authorization is denied, how can I modify the HttpContext to cause the framework subsequently does the right thing?

  10. sw_lasse says:

    Regarding the missing appendix Appendix G, “Authorization Strategies.” in “A guide to claims-based identity and access control” second edition by patterns & practices, Microsoft Corp. It is correct that the chapter never made it to the 2nd edition, however, it is in Drop #3 on codeplex, here: https://claimsid.codeplex.com/releases/view/65176 – from the changelog: “Two appendices on message exchanges between all involved parties and authorization strategies.”

  11. spring1975 says:

    I’m looking for a way to override the HandleUnauthorizedRequest method when using the [ClaimsAuthorize(“Read”, “SomeData”)] option.

    I’ve successfully set up an override by creating a new class with an override in it and applying with the filters.Add(new CustomClaimAuthorizeAttribute());

    However, that makes it check every action in the site (which I don’t want) and it’s no longer passing my attributes (“Read”, “SomeData”). How do I wire in the new class with the override in it when using the ClaimsAuthorize attribute?

    • I never tried that – why do you need to use the global filter? Why doesn’t it work as an attribute? In the worst case, write you own attribute.

      • spring1975 says:

        The point is, I don’t want to use the global filter, but the only way I’ve seen anyone wire in an override for HandleUnauthorizedRequest is by setting up a new class and then adding that class to the global filters.

        Why doesn’t it work as an attribute? Well, I know why, because I don’t know where to wire in the override code I have written to get picked up by the Thinktecture attributes solution. Which is what I’m asking here…

        Why recreate the wheel when the Thinktecture library is handling everything the way I want minus the clarity of how to override HandleUnauthorizedRequest? Is there no way to override this without writing my own attribute?

        It amazes me there aren’t more questions about this online. Unauthorized and not-authenticated are two completely different things. Yet, MS decided that a failure in both scenarios should just be sent back to the login page.

        If a user is already authenticated, but not authorized to view a page, they’re sent back to the login page (with a ReturnUrl parameter). If the user had checked ‘remember me’, they’re re-authenticated and forwarded to the ReturnUrl. A loop! Seriously?

        Even if the user didn’t have ‘remember me’ checked, the idea that a typical user would know why they were sent back to the login page, and better yet, know they need to log in with different credentials to access the page they just attempted is ludicrous. There’s nothing anywhere about passing any information to display feedback on the login page regarding the unauthorized attempt.

        Unauthorized requests are what the 401 error (unauthorized) or custom unauthorized error page is for. Feedback to the user.

  12. spring1975 says:

    I’m trying to override HandleUnauthorizedRequest when using the ClaimsAuthorize option, not the filter option. I’ve asked the question on stackoverflow and haven’t gotten a bite.
    http://stackoverflow.com/questions/23699959/claims-authorization-using-thinktecture-identitymodel

  13. But in both cases you are ultimately deriving from AuthorizeAttribute – why can’t you override the relevant methods?

  14. Vishwanath says:

    Hello Dominick

    I am trying to use ClaimsAuthorize and have tried to override the CheckAccess Method , I has used similar logic to whats in the Samples ,

    namespace ClaimsBasedAuthorization
    {
    public class AuthorizationManager : ClaimsAuthorizationManager
    {
    public override bool CheckAccess(AuthorizationContext context)
    {
    return true;
    }
    }
    }

    And the config has

    But i get this error , its a bit strange so am wondering if i missed something u said .

    {“The value of the property ‘type’ cannot be parsed. The error is: The type ‘ClaimsBasedAuthorization.AuthorizationManager, ClaimsBasedAuthorization’ cannot be resolved. Please verify the spelling is correct or that the full type name is provided.”}

  15. Toni says:

    I am getting the same error: “{“The value of the property ‘type’ cannot be parsed. The error is: The type ‘ClaimsBasedAuthorization.AuthorizationManager, ClaimsBasedAuthorization’ cannot be resolved. Please verify the spelling is correct or that the full type name is provided.”}”

    Vishwanath, have you been able to figure what the issue is? Thanks!

  16. Steven Volckaert says:

    Hello Dominic,

    I’m trying to use

    ClaimsAuthorization.CheckAccess(“Get”, “CustomerId”, id.ToString());

    In my API controllers to provide data level authorization. I understood from previous comments that a class inheriting System.Security.Claims.ClaimsAuthorizationManager should be created that implements the custom authorization logic.

    In my case, the authorization logic means querying the customer with the provided ID (id.ToString() above), as our Customer entities contain the ID of the organization it belongs to. The ID of the organization to which the principal belongs is part of its claims, so I can compare the two values and return false if they aren’t identical.

    I’ve checked your implementation of ClaimsAuthorization.CheckAccess(string, params[] string): Seems like the strings “CustomerId” and id.ToString() are stored in a Claim, both with claim type ClaimsAuthorization.ResourceType.

    Checking whether the claim with type ResourceType and value “CustomerId” exists in the principal’s claims collection is easy, but how do I reliably access the claim that contains the ID? Should I simply assume its the second one in the context.Resource collection?

    Thanks a lot for your help.

  17. Steven Volckaert says:

    I’m transforming claims (adding application-specific claims stored in the application’s database) in an OWIN middleware class, here called MyAuthenticationMiddleware.

    using System;
    using System.Collections.Generic;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.Owin;

    namespace Application.Service
    {
    public class MyAuthenticationMiddleware
    {
    private Func<IDictionary, Task> _next;

    public MyAuthenticationMiddleware(Func<IDictionary, Task> next)
    {
    _next = next;
    }

    public async Task Invoke(IDictionary env)
    {
    var context = new OwinContext(env);
    var principal = context.Request.User;

    if (principal != null)
    {
    var account = principal.Account();

    // Overwrite the principal with a new one that contains our application-specific claims.
    if (account != null)
    context.Request.User =
    new ClaimsPrincipal(
    identity: new ClaimsIdentity(principal.Identity, account.PermissionClaims())
    );
    }

    await _next(env);
    }
    }
    }

    After setting context.Request.User, ClaimsPrincipal.Current (and Thread.CurrentPrincipal) are referencing the same ClaimsPrincipal object as context.Request.User is. Before setting this property, the value is a RolePrincipal that’s coming from a WS-Federation token issued by our custom identity provider (a ThinkTecture IdentityServer).

    However, when my AuthorizationManager.CheckAccess method is invoked, ClaimsPrincipal.Current contains a this RolePrincipal object, not the ClaimsPrincipal object I’ve set in the OWIN middleware.

    As such I’m unable to use the out-of-the-box implementation of ClaimsAuthorizeAttribute and static method ClaimsAuthorization.CheckAccess(string, params[] string), because these internally pass ClaimsPrincipal.Current to the ClaimsAuthorizationManager.

    Any idea what I could be doing wrong?

  18. Amit says:

    Thank you. I am big fan of your tutorial at pluralsight and otherwise. I have one small question that I want to implement Row and Field level permissions with webapi. I am using Code First technique for EF at the backend. I have build the authorize as suggested by you. However, I am just getting confused on how best I can implement the same so that it is easy to manage.

    I have also introduced User Roles. Thus, I can bound these roles (Guid) against rows and also user (Guid) for CRUD operations. In addition, I also need to see how can I control field level security.

    I want to implement this at domain service level, not at SQL level.

    Will you be able to give any direction, or a framework, code sample to look at.

  19. Pingback: ClaimsPrincipalPermission and unit testing | www.davidarodriguez.com

  20. whitexacker says:

    hi and Thankyou for this Article.and i have a question.

    am using the Onion Architecture in my actual project with OWIN and ASP.NET Identity.i moved all the asp.net identity authenticathion logic to it’s own layer and made the UI MVC application depend on Interfaces in the Domaine.i use Ninject to do Dependency injection but i have a problem.

    i was trying to move the Authorization decisions making to it’s own layer.so i created a class AuthorizationProxy wich derives from ClaimsAuthorizationManager with a new constructor that accept an interface (IAuthorizationManager) defined in the domain core so i can use ninject to to inject the right implementation inside this constructor.after that and from within overriden CheckAccess i was hoping to delegate all the authorization decision making to the inctance injected inside the nex constructor.but i get a MissingMethodException indicating that the manager registered in the configuration file has no parameterless constructor.

    this Authorizationmanager is called by the CLR as you mentionned so it looks like it accept only a parameterless Ctor
    any idea?

  21. Hello!

    I have found an article which explains a simplified approach to authentication in ASP.NET MVC5 (http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown-part-deux). What I do like in the Khalid article is the simplicity. What if I want to make an activity based authorization? In the AuthenticationController I’m adding claims to the identity: (I don’t have a deep understanding of how do claims work)

    var identity = new ClaimsIdentity(
    claims: new [] {new Claim(ClaimTypes.Name, input.Username)},
    authenticationType: DefaultAuthenticationTypes.ApplicationCookie,
    nameType: ClaimTypes.Name,
    roleType: ClaimTypes.Role
    );

    Initially I was thinking to do as it was suggested in the article – to add role names to the identity.

    /*
    foreach(var role in user.Roles) {
    identity.AddClaim(new Claim(ClaimTypes.Role, role.Name));
    }
    */

    But what should I do to use activity based authorization? First, what claims should I add to the identity? How can I apply your approach?

    Thank you very much! God bless you!

    • No special claim types are required. You add the claims to the principal that you need in the authorization manager to come to a decision if the user is allowed or not. That could involve database/service lookups. No magic ;)

      • Yes, I have explored the Thinktecture project sources))
        Have some questions though:
        – Though I’ve decided to go on with resource-action authorization I’m just curious whether I could use `activity` (like “updatePost”, “viewLogs”) instead of `resource-action pair`. Well I know that AuthorizationContext uses `resource` and `action(s)`. And believe that AuthorizationContext is a requirement. Is there any workaround to this?
        – As for lookups. As I understand the signed in identity claims are stored inside a cookie. I don’t know how the whole workflow works but I assume that AuthorizationManager somehow has an access to that cookie. I defined an entity `UserPermission` which is a separate entity that holds ids of resource/action and has a name. Then at login I’m planning to load resource-actions pairs from all user permissions. Is it right?

      • A correction to my response below. I’m planning to load `resource-actions` pairs from UserPermissions into identity at login. Am I on the right track with that?

  22. Rodrigo says:

    Exist claims limits ?

    My project have a 100 controller, in simple Crud exist 4 action, then I’m have 400 claims

    mycontroller1 => list,add,edit,remove

  23. rosdi says:

    Hi, how do you do menu security trimming based on this? I am wondering if I can hide/display menus based on their claims..

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s