Custom Principals in WCF with Geneva

WCF has an extensibility point to set your own IPrincipal implementation on Thread.CurrentPrincipal (I wrote about that here). Geneva uses this mechanism to set its IClaimsPrincipal (wrote about that here).

Since the standard “slot” for custom principals is already used by Geneva, it was unclear to me how to set your own IPrincipal after Geneva has done its work. With a little help from the Geneva team (thanks Jan) – I found a way that works.

You can replace the principal in a service authorization manager via the Properties collection on the authorization context. Voodoo.

class AuthorizationManager : IdentityModelServiceAuthorizationManager
{
    public override bool CheckAccess(OperationContext operationContext, ref Message message)
    {
        base.CheckAccess(operationContext, ref message);

        // action header to get to the request operation
        string action = operationContext.IncomingMessageHeaders.Action;

        // properties collection holds the principal that goes on Thread.CurrentPrincipal
        var properties = operationContext
                        .ServiceSecurityContext
                        .AuthorizationContext
                        .Properties;

        // retrieve current principal
        IClaimsPrincipal principal = properties[“Principal”] as IClaimsPrincipal;
       
        // create custom principal
        var customPrincipal = new CustomClaimsPrincipal(principal, “some value”);
       
        // set the custom principal
        properties[“Principal”] = customPrincipal;
           
        return Authorize(action, customPrincipal);
    }

    private bool Authorize(string action, CustomClaimsPrincipal principal)
    {
        // do whatever authZ logic you have
        return true;
    }
}

public class CustomClaimsPrincipal : ClaimsPrincipal
{
    public CustomClaimsPrincipal(IClaimsPrincipal principal, string customValue)
      : base(principal)
    {
        CustomPropery = customValue;
    }

    public string CustomPropery { get; set; }
}

Afterwards register this class in the ServiceAuthorizationBehavior.

Be aware that this gets called on every request – so don’t put expensive operations in the custom principal creation code.

This entry was posted in IdentityModel, WCF. Bookmark the permalink.

Leave a comment