US / UK-EMEA / Contact Ask DevelopMentor a Question800.699.1932

Improving WIF’s Claims-based Authorization - Part 1

by Dominick Baier

As mentioned in my last article, I made several additions to WIF’s built-in authorization infrastructure to make it more flexible and easy to use.

The foundation for all this work is that you have to be able to directly call the registeredClaimsAuthorizationManager. The following snippet is the universal way to get to the WIF configuration that is currently in effect:

public
 static ServiceConfiguration
ServiceConfiguration
{
    get
    {
        if (OperationContext.Current == null
)
        {
            // no WCF
            return FederatedAuthentication
.ServiceConfiguration;
        }

        // search message property
        if (OperationContext.Current.IncomingMessageProperties.
ContainsKey(
"ServiceConfiguration"
))
        {
            var configuration = OperationContext.Current.
IncomingMessageProperties[
"ServiceConfiguration"] as ServiceConfiguration
;

            if (configuration != null)
            {
                return
configuration;
            }
        }

        // return configuration from configuration file
        return new ServiceConfiguration();
    }
}  

From here you can grab ServiceConfiguration.ClaimsAuthoriationManager which give you direct access to theCheckAccess method (and thus control over claim types and values).


I then created the following wrapper methods:
 
public static bool CheckAccess(string resource, string action)
{
    return CheckAccess(resource, action, Thread.CurrentPrincipal as IClaimsPrincipal);
}


public
 static bool CheckAccess(string resource, string action, IClaimsPrincipal
principal)
{
    var context = new AuthorizationContext(principal, resource, action);

    return
 AuthorizationManager.CheckAccess(context);
}

public
 static bool CheckAccess(Collection<Claim> actions, Collection<Claim
> resources)
{
    return CheckAccess(new AuthorizationContext(
        Thread
.CurrentPrincipal.AsClaimsPrincipal(), resources, actions));
}

public
 static bool CheckAccess(AuthorizationContext
 context)
{
    return AuthorizationManager.CheckAccess(context);
}

I also created the same set of methods but called DemandAccess. They internally use CheckAccess and will throw a SecurityException when false is returned.

All the code is part of Thinktecture.IdentityModel on Codeplex – or via NuGet (Install-Package Thinktecture.IdentityModel).

public
 void AddCustomer(Customer
 customer)
{
    if (Thread.CurrentPrincipal.IsInRole("Sales"
))
    {
        // add customer

    }
}

In code reviews I’ve seen tons of code like this. What I don’t like about this is, that two concerns in your application get tightly coupled: business and security logic.

But what happens when the security requirements change – and they will (e.g. members of the sales role and some other people from different roles need to create customers)? Well – since your security logic is sprinkled across your project you need to change the security checks in all relevant places (and make sure you don’t forget one) and you need to re-test, re-stage and re-deploy the complete app. This is clearly not what we want.

WIF’s claims-based authorization encourages developers to separate business code and authorization policy evaluation. This is a good thing. So the same security check with WIF’s out-of-the box APIs would look like this:

public
 void AddCustomer(Customer
 customer)
{
    try

    {
        
ClaimsPrincipalPermission.CheckAccess("Customer","Add");
 
        // add customer

    }
    
catch (SecurityException ex)
    {
        // access denied

    }
}

You notice the fundamental difference? The security check only describes whatthe code is doing (represented by a resource/action pair) – and does not statewho is allowed to invoke the code. As I mentioned earlier – the who is most probably changing over time – the what most probably not.

The call to ClaimsPrincipalPermission hands off to another class called theClaimsAuthorizationManager. This class handles the evaluation of your security policy and is ideally in a separate assembly to allow updating the security logic independently from the application logic (and vice versa).

The claims authorization manager features a method called CheckAccess that retrieves three values (wrapped inside an AuthorizationContext instance) – action (“add”), resource (“customer”) and the principal (including its claims) in question. CheckAccess then evaluates those three values and returns true/false.

I really like the separation of concerns part here. Unfortunately there is not much support from Microsoft beyond that point. And without further tooling and abstractions the CheckAccess method quickly becomes *very* complex. But still I think that is the way to go.
In the next post I will tell you what I don’t like about it (and how to fix it).
Connect
Signup for our Free Newsletter!
Latest news
Twitter Feed MORE
Got an email from a developer in Holland about my Onion Architecture blog post http://t.co/Z5DTvJob Nice to have a worldwide audience! #dm
1 day ago (details)
There is something to this statement: Why Quit? Because They Have Bigger Monitors http://t.co/9FrGETG5 #dm (via @mkennedy)
2 days ago (details)
Testimonials
  • Rod da Silva felt very confident in his product knowledge and experience. Bob C.