Question

In my WCF webservice web.config I have the following under serviceBehaviors:

<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="RoleProvider" />

This allows me to use the asp.net role provider and control access to the web service calls with the following attribute:

[PrincipalPermission(SecurityAction.Demand, Role = "Admin")]

I would like to know how I can use the above and also incorporate a custom principal as defined below.

public class UserPrincipal : IPrincipal
{
    List<string> roleList = null;

    public const string ROLE_ADMIN         = "Admin";
    public const string ROLE_DATAENTRY     = "DataEntry";
    public const string ROLE_READONLY      = "ReadOnly";

    public UserPrincipal(IIdentity identity, string[] roles)
    {
        Identity = identity;            
        roleList = new List<string>(roles);      
    }

    public IIdentity Identity
    {
        get { return identity; }
    }

    public bool IsInRole(string role)
    {
        return roleList.Contains(role);
    }

    public bool CanEdit()
    {
        if (IsInRole(ROLE_ADMIN))
            return true;       
        else if (IsInRole(ROLE_DATAENTRY))
            return true;
        else 
            return false;
    }

    public bool CanView()
    {
        if (IsInRole(ROLE_ADMIN))
            return true;        
        else if (IsInRole(ROLE_DATAENTRY))
            return true;
        else if (IsInRole(ROLE_READONLY))
            return true;
        else
            return false;
    }

}

I would like to then use the CanView and CanEdit calls from within the service methods.

Where in the WCF service can I replace the default principal with my extended user principal?

Was it helpful?

Solution

Here is what I came up with in case someone else finds it useful.

Web.config:

 <behaviors>
      <serviceBehaviors>
        <behavior name="customServiceBehaviour">
          <serviceAuthorization principalPermissionMode="Custom" >
            <authorizationPolicies>
              <add policyType="Services.Host.CustomRolesPolicy, Services.Host" />
            </authorizationPolicies>            
          </serviceAuthorization>
        </behavior>            
      </serviceBehaviors>
  </behaviors>

CustomRolesPolicy:

    public class CustomRolesPolicy : IAuthorizationPolicy
    {
            Guid id = Guid.NewGuid();

            public bool Evaluate(EvaluationContext evaluationContext, ref object state)
            {
                // will hold the combined roles
                List<string> roles = new List<string>();

                // get the authenticated client identity
                IIdentity client = GetClientIdentity(evaluationContext);

                var config = new NameValueCollection();


                config.Add("applicationName", "/application_name");
                config.Add("connectionStringName", "APPSEC_ASPNET");                

                var roleProvider = new CustomRoleProvider();
                roleProvider.Initialize("CustomRoleProvider", config);

                roles.AddRange(roleProvider.GetRolesForUser(client.Name));


                evaluationContext.Properties["Principal"] =
                    new UserPrincipal(client, roles.ToArray());


                return true;
            }

            public System.IdentityModel.Claims.ClaimSet Issuer
            {
                get { return ClaimSet.System; }
            }

            public string Id
            {
                get { return id.ToString(); }
            }

            private IIdentity GetClientIdentity(EvaluationContext evaluationContext)
            {
                object obj;
                if (!evaluationContext.Properties.TryGetValue("Identities", out obj))
                    throw new Exception("No Identity found");

                IList<IIdentity> identities = obj as IList<IIdentity>;
                if (identities == null || identities.Count <= 0)
                    throw new Exception("No Identity found");

                return identities[0];
            }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top