BizTalk WCF-WebHTTP Basic Authentication Authorization Manager

The scenario,

  • BizTalk Server 2013
  • WCF-WebHTTP receive location
  • Basic Authentication
  • Need Authorizations!!!!

First up create a C# class library and copy the below code into it.  Add a reference to System.ServiceModel; System.ServiceModel.Web, and System.Configuration.  Compile it and add to the gac.

using System;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Configuration;
using System.Threading.Tasks;
using System.ServiceModel.Web;
using System.Collections.Generic;
using System.ServiceModel.Description;
using System.ServiceModel.Configuration; 

namespace ServiceBehaviors
{
    public class BizTalkAuthorizationManager : ServiceAuthorizationManager
    {
        private string m_allowedUserList; 

        public BizTalkAuthorizationManager(string allowedUserList)
        {
            this.m_allowedUserList = allowedUserList;
        } 

        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            //Extract the Authorization header, and parse out the credentials converting the Base64 string:
            var authHeader = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
            bool retval = false; 

            if ((authHeader != null) && (authHeader != string.Empty))
            {
                var svcCredentials = System.Text.ASCIIEncoding.ASCII
                        .GetString(Convert.FromBase64String(authHeader.Substring(6)))
                        .Split(':');
                string headerUsername = svcCredentials[0];
                string headerPassword = svcCredentials[1]; 

                // Strip out any domain name
                if (headerUsername.Contains("\\"))
                    headerUsername = headerUsername.Split('\\')[1]; 

                string[] users = m_allowedUserList.Split(new string[] { ":" }, StringSplitOptions.None); 

                foreach (string user in users)
                {
                    if (user.ToUpper() == headerUsername.ToUpper())
                    {
                        retval = true;
                        break;
                    }
                }
            }
            return retval;
        }
    } 

    public class BizTalkAuthorizationManagerCustomBehavior : IServiceBehavior
    {
        private string m_allowedUserList; 

        public BizTalkAuthorizationManagerCustomBehavior(string allowedUserList)
        {
            this.m_allowedUserList = allowedUserList;
        } 

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            ServiceAuthorizationBehavior authBehavior = serviceDescription.Behaviors.Find<ServiceAuthorizationBehavior>(); 

            // Pass in list of allowed users during config setup
            authBehavior.ServiceAuthorizationManager = new BizTalkAuthorizationManager(this.m_allowedUserList);
            ((IServiceBehavior)authBehavior).ApplyDispatchBehavior(serviceDescription, serviceHostBase);
        } 

        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase hostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        { 

        } 

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { 

        }
    } 

    public class BizTalkCustomBehaviorElement : BehaviorExtensionElement
    {
        /// Config property for BizTalk admin console
        [ConfigurationProperty("allowedUsersList", IsRequired = false, DefaultValue = "")]
        public string AllowedUsersList
        {
            get { return (string)base["allowedUsersList"]; }
            set { base["allowedUsersList"] = value; }
        } 

        protected override object CreateBehavior()
        {
            return new BizTalkAuthorizationManagerCustomBehavior(AllowedUsersList);
        } 

        public override Type BehaviorType
        {
            get
            {
                return typeof(BizTalkAuthorizationManagerCustomBehavior);
            }
        } 

    }
} 

Next register your new custom authorization manager within the machine.config. Your entry should look something like the below.  Update both the Framework and Framework64 copies of the machine.config.

<system.serviceModel>
		<extensions>
			<behaviorExtensions>
                            <add name="BizTalkAuthorizationManager" type="ServiceBehaviors.BizTalkCustomBehaviorElement, ServiceBehaviors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=aaabbbcccdddeeef"/>

Now restart IIS, restart your host instances, restart the BizTalk administration console. Open the WCF-WebHTTP receive location and configure the properties. Go to the Bindings tab and configure as per the below.  The allowedUserList property can be thought of as the old IIS url authorization <allow user=””/>.  An empty list is the same as <deny user=”*/”>.

Screen Shot 2014-05-26 at 9.56.57 PM

Obviously the above code works with basic authentication and the HTTP authorization header.  You can extend the code to support windows authentication etc without much effort.  The source of the authorizations list can also be tweaked to be SSO etc.  A couple of things not to forget.  On your web service enable basic authentication in IIS, disable anonymous, on your WCF-WebHTTP receive location set the security tab as per below.

Screen Shot 2014-05-26 at 10.13.48 PM

Advertisements
This entry was posted in BizTalk Server. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s