Question

I am developing a WCF service, with a custom USERNAME-PASSWORD validator.

I have a CustomUserNameValidator that inherits from UserNamePasswordValidator.

I also use a CustomAuthorizationPolicy that inherits from IAuthorizationPolicy.

The Evaluate method of the custom authorization policy looks like this:

    // this method gets called after the authentication stage
    public bool Evaluate(EvaluationContext evaluationContext, ref object state)
    {
        // get the authenticated client identity
        IIdentity client = GetClientIdentity(evaluationContext);

        // set the custom principal
        evaluationContext.Properties["Principal"] = new CustomPrincipal(client);

        return true;
    }

As you can see - I create a new CustomPrincipal object in every call to Evaluate (which is done in every operation that is called on the service).

This is what my CustomPrincipal constructor looks like:

    public CustomPrincipal(IIdentity identity)
    {
        IdentityObject = identity;
        GetUser(IdentityObject.Name);
        EnsureRoles();
    }

The GetUser and EnsureRoles methods go to an SQL database, to check the roles for the user.

My question is - why does this have to happen on every operation ??

Why does the creation of a CustomPrincipal happen on every operation and not just on the first time the client connects to the service ?

It makes no sense to me why for every operation called on the service - the 'CustomPrincipal' will go to the database and re-fetch the user, and all of his roles...

[Update] This is what my query service interface looks like:

[ServiceContract(Namespace = "http://www.my1fj.com/QueryService/2012/", SessionMode = SessionMode.Required, ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public interface IQueryService
{
     // Some operations
}
Was it helpful?

Solution

I hope your service is a per call service and in the per call services the authentication check will happen in every call but in the case of per session services the check happens only at the beginning of the session (if security negotiation is turned on).

..from here

Instead of hitting the db every time you can cache them in the service.

Update:

A service is a per-call/per-session/singleton is decided by the InstanceContextMode property of the ServiceBehavior that is applied over the service class.

Ex.

[ServiceContract]
interface IMyContract {...}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
class MyService : IMyContract {...}

To know more about please check this post. To know more about the InstanceContextMode property check this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top