12 March 2007

How-To: Implement a WCF Authorization Manager Using AzMan

This article intends to explain how to use AzMan to implement a custom authorization policy in WCF.

AzMan (Windows Authorizacion Manager) is a role-based application framework which provides runtime access validation methods, storage, and a UI to manage access control. The Authorization Manager runtime is separated from the authorization policy store, which may be stored in Active Directory, ADAM, or XML. AzMan is composed of two parts:

  1. Runtime: Provided by AZROLES.DLL, exposes a set of COM interfaces used by applications that employ role-based security.
  2. Administration UI: MMC snap-in that you can try out by running AZMAN.MSC or by adding the Authorization Manager snap-in to your MMC console of choice:

Follow these steps to use AzMan from within a custom authorization policy in your WCF Service:

1. Put AzMan to work with ADAM as the authorization policy store.

As I said before, the authorization policy store is independent from the authorization runtime. In this example I used ADAM as the policy store, but you can use an xml file as well.

1.1. Download and Install AzMan: AzMan comes with Windows Server 2003. For othe versions of windows, the Windows Server 2003 SP1 Administration ToolPack can be installed.

1.2. Download ADAM and create a new ADAM Instance (not available for Windows Vista)

1.3 Configure AzMan to use ADAM as the policy store

Steps 1.2 and 1.3 are explained in detail in steps 1 and 2 of this article, so you can follow the from there.

The ADAM instance can be administrated from the Adam ADSI Edit tool:

2. Ask for the user's permissions programmatically.

Once you have your role-based policy created in AzMan, is time to know how to ask for permissions programmatically.

2.1 In your .Net project add a reference to the Microsoft.Interop.Security.AzRoles assembly (found at %AzMan Download Dir%\Windows(R) 2000 Authorization Manager Runtime\PIA\1.2).

2.2 In order to connect to your AzMan application you can use the following lines of code:

AzAuthorizationStore store = new AzAuthorizationStore();
store.Initialize(0, ConfigurationManager.AppSettings["azManStore"], null);
IAzManApplication app = store.OpenApplication(
ConfigurationManager.AppSettings["azManAppName"], null);

The azManStore configuration entry is of the form:

"msldap://localhost:389/CN=AzManADAMStore,OU=SecNetPartition,O=SecNet,C=AR" for an ADAM repository, or
"msxml://c:/TestAuthStore.xml" for an xml file repository

2.3 To ask if a user has access to a given operation you need to istantiate an IAzClientContext from the user identity and then ask the context whether it has access to a given operation.

To obtain the client context from his user name:

IAzClientContext ctx = app.InitializeClientContextFromName(user, domain, null);

To obtain it from a System.Security.Principal.WindowsIdentity:

HandleRef handle = new HandleRef(this, identity.Token);
IAzClientContext ctx = app.InitializeClientContextFromToken(
(UInt64)handle.Handle, 0);

To ask for access to a given operation:

object[] operations = { (object)operationId };
object[] scopes = { (object)"" };
object[] results = (object[])context.AccessCheck(app.Name, (object)scopes, (object)operations, null, null, null, null, null);

If the result is 0 the access is granted.

Note that the query is made for the operation id, as it was entered in the AzMan operation definition. Usually you'll need a mapping between the operations ids and some friendly name.


3. Implement your a WCF custom Authorization Manager that relies on AzMan for authorization.

Now we have code access to AzMan to query for authorization, we want to integrate that to our WCF Service. We will implement a custom authorizationManager for that, since is the WCF natural extensibility point for authorization (although you can do it in a custom behavior also, the AuthorizationManager would be more accurate).

The custom AuthorizationManager must derive from System.ServiceModel.ServiceAuthorizationManager and override the CheckAccessCore method. For more information see How To: Create a Custom AuthorizationManager for a Service

In this example we will obtain the required action and the username from the operationContext and then use our AzMan utility class (AthorizationRepository) to ask whether the user has access to the given operation.

class MyAuthorizationManager : ServiceAuthorizationManager {

protected override bool CheckAccessCore(OperationContext operationContext) {

//Instanciate our AzMan utility class
AuthorizationRepository azMan = new AuthorizationRepository();

//Obtain the requested action from the context
string action = operationContext.RequestContext.RequestMessage.Headers.Action;

// Iterate through the various claimsets in the authorization context // to obtain the user name
foreach (ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets) {

foreach (Claim c in cs.FindClaims(ClaimTypes.Name,
Rights.PossessProperty)) {

string userName = c.Resource.ToString();
//check access
if (azMan.HasAccess(userName, action)) {
return true;
}
}
}
return false;
}
}

Hope it result useful!

Some links:

AzMan
Developing Applications Using Windows Authorization Manager
Use Role-Based Security in Your Middle Tier .NET Apps with Authorization Manager

ADAM
Windows Server 2003 Active Directory Application Mode
How To: Use ADAM for Roles in ASP.NET 2.0

WCF Authorization
How To: Create a Custom AuthorizationManager for a Service (WCF)
How To: STS/Windows Authentication with ADAM/AD, Roles in AzMan with WCF
(using WCF behaviours)


2 comments:

Dan Mork said...

Great article! Thanks!

For your readers, you might need to consider Endpoint & Action to determine whether the sender is authorized. For example, you have a service urn:UsefulService with an operation urn:UsefulOperation and customers PreferredConsumer and RegularConsumer. Your urn:UsefulService is accessible via http://you.com/HighAvailabilityEndpoint and http://you.com/RegularEndpoint. You might not want to authorize a urn:UsefulOperation message from RegularCustomer on http://you.com/HighAvailabilityEndpoint .

Cheers,
Dan Mork

Anonymous said...

Hi,

Does this solution work with PerCall services?

Kind Regards,
Russ.