What I like about WIF’s Claims-based Authorization
- by Your DisplayName here!
In “traditional” .NET with its IPrincipal interface and IsInRole method, developers
were encouraged to write code like this:
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 what the
code is doing (represented by a resource/action pair) – and does not state who 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 the ClaimsAuthorizationManager.
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).