Translate

Monday 14 March 2016

Custom Service Authorization Manager for WCF Service

The IT industry divides security into two parts: 

1. Authentication 2. Authorization. 

Authentication verifies that users are who he claims to be. This can be done in a couple of ways: certificates, username/password, windows credentials, …

Authorization will decide what an (authenticated) user is allowed to execute. 

Implementing restricted access to a WCF service can be done in a couple of ways. 
  • A first option is to mark methods with the declarative PrincipalPermissionAttribute to restrict access to certain roles or users. 
  • An another option is to imperatively check the credentials of the current user.

Both of these methods have the drawback that they result in a lot of duplication when you have multiple service methods. Because duplication is the root of all evil, the creators of WCF have foreseen an extension point in WCF to implement authorization in a generic way: the ServiceAuthorizationManager.

Generic implementation to authorize access to a WCF service:

Implementation


Implementing a ServiceAuthorizationManager is straightforward; you need to extend the class “ServiceAuthorizationManager” and you need to override the method “CheckAccessCore”. In this small example, I will restrict access to my service to users of the windows group “Administrators”.

public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        try
        {
            ServiceSecurityContext securityContext = operationContext.ServiceSecurityContext;
            WindowsIdentity callingIdentity = securityContext.WindowsIdentity;
 
            WindowsPrincipal principal = new WindowsPrincipal(callingIdentity);
            return principal.IsInRole("Administrators");
        }
        catch (Exception)
        {
            return false;
        }
    }
}

Now that our custom ServiceAuthorizationManager has been implemented, we need to hook it into the WCF pipeline. The most easy way to do is, by using the web.config or app.config file.

<system.serviceModel>
   <!-- Define service and endpoints --> 
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServiceBehavior">
                <serviceAuthorization serviceAuthorizationManagerType="MyNamespace.MyServiceAuthorizationManager, MyAssembly" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>