none
WCF adapter - how to implement authorization? RRS feed

  • Question

  • Hi all

     

    If I was writing a "normal" (i.e. non-BizTalk) WCF service I would lock down operations using either the PrincipalPermission attribute or do an IsInRole check in the code, but how would achieve a similar thing with the BizTalk WCF adapter (if it's even possible)?

     

    Thanks in advance

     

    Andy

     

    Wednesday, January 16, 2008 2:44 PM

Answers

  • Yes, it is possible.

    You can create your own custom service authorization behavior, and use it with WCF-Custom adapter.

    I'm adding the code block below

     

    1- Compile the code below, and install it to GAC

    2-  Add the following entry to machine.config file

    <system.serviceModel>

        <extensions>

          <behaviorExtensions>

            <add name="myCustomAuth" type="WcfServiceBehaviors.MyCustomBehaviorElement, WcfServiceBehaviors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PUBLIC KEY OF YOUR DLL" />

          </behaviorExtensions>

        </extensions>

      </system.serviceModel>

     

     

    3- Restart BTS service, and reopen administration console if it's already open.

    4- Create a receive location with WCF-Custom adapter. Choose whatever binding you want. Go to behaviors tab, and add the myCustomAuth binding by right clicking on the serviceBehavior and choosing add extension

     

     

    Code Block

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.ServiceModel;

    using System.ServiceModel.Channels;

    using System.ServiceModel.Description;

    using System.ServiceModel.Configuration;

    using System.IdentityModel.Policy;

    using System.IdentityModel.Claims;

    using System.Security.Principal;

    namespace WcfServiceBehaviors

    {

    public class MyCustomServiceAuthorizationManager : ServiceAuthorizationManager

    {

    protected override bool CheckAccessCore(OperationContext operationContext){

    if (!base.CheckAccessCore(operationContext))

    {

    return false;

    }

    AuthorizationContext authCtx = operationContext.ServiceSecurityContext.AuthorizationContext;

    //you can do your custom authorization here

    //authCtx.ClaimSets

    //authCtx.Properties["Principal"]

    //if you want to do your authorization based on the operation, you can try using operationContext.EndpointDispatcher.ContractName

    return true;

    }

    }

    public class MyCustomBehaviorElement : BehaviorExtensionElement

    {

    protected override object CreateBehavior()

    {

    return new MyCustomServiceBehavior();

    }

    public override Type BehaviorType

    {

    get { return typeof(MyCustomServiceBehavior); }

    }

    }

    public class MyCustomServiceBehavior : IServiceBehavior

    {

    #region IServiceBehavior Members

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)

    {

    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

    {

    ServiceAuthorizationBehavior authBehavior = serviceDescription.Behaviors.Find<ServiceAuthorizationBehavior>();

    authBehavior.ServiceAuthorizationManager = new MyCustomServiceAuthorizationManager();

    ((IServiceBehavior)authBehavior).ApplyDispatchBehavior(serviceDescription, serviceHostBase);

    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

    {

    }

    #endregion

    }

    }

     

     

     

     

     

     

    Wednesday, January 16, 2008 10:15 PM

All replies

  • Yes, it is possible.

    You can create your own custom service authorization behavior, and use it with WCF-Custom adapter.

    I'm adding the code block below

     

    1- Compile the code below, and install it to GAC

    2-  Add the following entry to machine.config file

    <system.serviceModel>

        <extensions>

          <behaviorExtensions>

            <add name="myCustomAuth" type="WcfServiceBehaviors.MyCustomBehaviorElement, WcfServiceBehaviors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PUBLIC KEY OF YOUR DLL" />

          </behaviorExtensions>

        </extensions>

      </system.serviceModel>

     

     

    3- Restart BTS service, and reopen administration console if it's already open.

    4- Create a receive location with WCF-Custom adapter. Choose whatever binding you want. Go to behaviors tab, and add the myCustomAuth binding by right clicking on the serviceBehavior and choosing add extension

     

     

    Code Block

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.ServiceModel;

    using System.ServiceModel.Channels;

    using System.ServiceModel.Description;

    using System.ServiceModel.Configuration;

    using System.IdentityModel.Policy;

    using System.IdentityModel.Claims;

    using System.Security.Principal;

    namespace WcfServiceBehaviors

    {

    public class MyCustomServiceAuthorizationManager : ServiceAuthorizationManager

    {

    protected override bool CheckAccessCore(OperationContext operationContext){

    if (!base.CheckAccessCore(operationContext))

    {

    return false;

    }

    AuthorizationContext authCtx = operationContext.ServiceSecurityContext.AuthorizationContext;

    //you can do your custom authorization here

    //authCtx.ClaimSets

    //authCtx.Properties["Principal"]

    //if you want to do your authorization based on the operation, you can try using operationContext.EndpointDispatcher.ContractName

    return true;

    }

    }

    public class MyCustomBehaviorElement : BehaviorExtensionElement

    {

    protected override object CreateBehavior()

    {

    return new MyCustomServiceBehavior();

    }

    public override Type BehaviorType

    {

    get { return typeof(MyCustomServiceBehavior); }

    }

    }

    public class MyCustomServiceBehavior : IServiceBehavior

    {

    #region IServiceBehavior Members

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)

    {

    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

    {

    ServiceAuthorizationBehavior authBehavior = serviceDescription.Behaviors.Find<ServiceAuthorizationBehavior>();

    authBehavior.ServiceAuthorizationManager = new MyCustomServiceAuthorizationManager();

    ((IServiceBehavior)authBehavior).ApplyDispatchBehavior(serviceDescription, serviceHostBase);

    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

    {

    }

    #endregion

    }

    }

     

     

     

     

     

     

    Wednesday, January 16, 2008 10:15 PM
  • Many thanks for your help.

     

    I was already on the right lines before starting this thread - I had already implemented my own IAuthorizationPolicy (where I create the principal and populate its roles), and had also tried implementing a custom ServiceAuthorizationManager class, but I just couldn't find a way to access the principal object until I saw your code.

     

    Regards

     

    Andy

    Friday, January 18, 2008 2:05 PM