Export (0) Print
Expand All

How to: Create a Custom Authorization Manager for a Service

The Identity Model infrastructure in Windows Communication Foundation (WCF) supports an extensible claims-based authorization model. Claims are extracted from tokens and optionally processed by custom authorization policies and then placed into an AuthorizationContext. An authorization manager examines the claims in the AuthorizationContext to make authorization decisions.

By default, authorization decisions are made by the ServiceAuthorizationManager class; however these decisions can be overridden by creating a custom authorization manager. To create a custom authorization manager, create a class that derives from ServiceAuthorizationManager and implement CheckAccessCore method. Authorization decisions are made in the CheckAccessCore method, which returns true when access is granted and false when access is denied.

If the authorization decision depends on the contents of the message body, use the CheckAccess method.

Because of performance issues, if possible you should redesign your application so that the authorization decision does not require access to the message body.

Registration of the custom authorization manager for a service can be done in code or configuration.

To create a custom authorization manager

  1. Derive a class from the ServiceAuthorizationManager class.

    
    public class MyServiceAuthorizationManager : ServiceAuthorizationManager
    {
    
    
    
  2. Override the CheckAccessCore(OperationContext) method.

    Use the OperationContext that is passed to the CheckAccessCore(OperationContext) method to make authorization decisions.

    The following code example uses the FindClaims(String, String) method to find the custom claim http://www.contoso.com/claims/allowedoperation to make an authorization decision.

    
    	protected override bool CheckAccessCore(OperationContext operationContext)
    	{                
    	  // Extract the action URI from the OperationContext. Match this against the claims
    	  // in the AuthorizationContext.
    	  string action = operationContext.RequestContext.RequestMessage.Headers.Action;
    	  
    	  // Iterate through the various claim sets in the AuthorizationContext.
    	  foreach(ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
    	  {
    		// Examine only those claim sets issued by System.
    		if (cs.Issuer == ClaimSet.System)
    		{
    		  // Iterate through claims of type "http://www.contoso.com/claims/allowedoperation".
                foreach (Claim c in cs.FindClaims("http://www.contoso.com/claims/allowedoperation", Rights.PossessProperty))
    		  {
    			// If the Claim resource matches the action URI then return true to allow access.
    			if (action == c.Resource.ToString())
    			  return true;
    		  }
    		}
    	  }
    	  
    	  // If this point is reached, return false to deny access.
    	  return false;                 
    	}
    
    
    

To register a custom authorization manager using code

  • Create an instance of the custom authorization manager and assign it to the ServiceAuthorizationManager property.

    The ServiceAuthorizationBehavior can be accessed using Authorization property.

    The following code example registers the MyServiceAuthorizationManager custom authorization manager.

    
    		// Add a custom authorization manager to the service authorization behavior.
    		serviceHost.Authorization.ServiceAuthorizationManager = 
                       new MyServiceAuthorizationManager();
    
    
    

To register a custom authorization manager using configuration

  1. Open the configuration file for the service.

  2. Add a <serviceAuthorization> element to the <behaviors>.

    To the <serviceAuthorization> element, add a serviceAuthorizationManagerType attribute and set its value to the type that represents the custom authorization manager.

  3. Add a binding that secures the communication between the client and service.

    The binding that is chosen for this communication determines the claims that are added to the AuthorizationContext, which the custom authorization manager uses to make authorization decisions. For more details about the system-provided bindings, see System-Provided Bindings.

  4. Associate the behavior to a service endpoint, by adding a <service> element and set the value of the behaviorConfiguration attribute to the value of the name attribute for the <behavior> of <serviceBehaviors> element.

    For more information about configuring a service endpoint, see How to: Create a Service Endpoint in Configuration.

    The following code example registers the custom authorization manager Samples.MyServiceAuthorizationManager.

    <configuration>
      <system.serviceModel>
        <services>
          <service 
              name="Microsoft.ServiceModel.Samples.CalculatorService"
              behaviorConfiguration="CalculatorServiceBehavior">
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
              </baseAddresses>
            </host>
            <endpoint address=""
                      binding="wsHttpBinding_Calculator"
                      contract="Microsoft.ServiceModel.Samples.ICalculator" />
          </service>
        </services>
        <bindings>
          <WSHttpBinding>
           <binding name = "wsHttpBinding_Calculator">
             <security mode="Message">
               <message clientCredentialType="Windows"/>
             </security>
            </binding>
          </WSHttpBinding>
    </bindings>
        <behaviors>
          <serviceBehaviors>
            <behavior name="CalculatorServiceBehavior">
              <serviceAuthorization serviceAuthorizationManagerType="Samples.MyServiceAuthorizationManager,MyAssembly" />
             </behavior>
         </serviceBehaviors>
       </behaviors>
      </system.serviceModel>
    </configuration>
    
    Caution noteCaution

    Note that when you specify the serviceAuthorizationManagerType, the string must contain the fully qualified type name. a comma, and the name of the assembly in which the type is defined. If you leave out the assembly name, WCF will attempt to load the type from System.ServiceModel.dll.

The following code example demonstrates a basic implementation of a ServiceAuthorizationManager class that includes overriding the CheckAccessCore method. The example code examines the AuthorizationContext for a custom claim and returns true when the resource for that custom claim matches the action value from the OperationContext. For a more complete implementation of a ServiceAuthorizationManager class, see Authorization Policy.


  public class MyServiceAuthorizationManager : ServiceAuthorizationManager
  {
	protected override bool CheckAccessCore(OperationContext operationContext)
	{                
	  // Extract the action URI from the OperationContext. Match this against the claims
	  // in the AuthorizationContext.
	  string action = operationContext.RequestContext.RequestMessage.Headers.Action;
	  
	  // Iterate through the various claim sets in the AuthorizationContext.
	  foreach(ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
	  {
		// Examine only those claim sets issued by System.
		if (cs.Issuer == ClaimSet.System)
		{
		  // Iterate through claims of type "http://www.contoso.com/claims/allowedoperation".
            foreach (Claim c in cs.FindClaims("http://www.contoso.com/claims/allowedoperation", Rights.PossessProperty))
		  {
			// If the Claim resource matches the action URI then return true to allow access.
			if (action == c.Resource.ToString())
			  return true;
		  }
		}
	  }
	  
	  // If this point is reached, return false to deny access.
	  return false;                 
	}
  }


Show:
© 2014 Microsoft