Zulfiqar's weblog

Architecture, security & random .Net

Archive for February, 2008

Windows authentication for IIS hosted WCF Service

Posted by zamd on February 15, 2008

Security settings for this service require ‘Anonymous’ Authentication but it is not enabled for the IIS application that hosts this service.

I have seen people struggling while configuring integrated windows authentication for their IIS hosted WCF service and are getting above exception. There are two settings required to make this work.

·         First enable Integrated Windows Authentication on IIS

·         Set the clientCredentialType to Windows

Here is a sample binding to enable windows authentication in IIS.

<bindings>

  <basicHttpBinding>

    <binding name=basicHttpBinding IMyService>

      <security mode=TransportCredentialOnly>

        <transport clientCredentialType=Windows/>

      </security>

    </binding>

  </basicHttpBinding>

</bindings>

However even after making these two changes you might still be getting the exception and the prime reason is that one of the service endpoints (most likely the MEX endpoint) still requires anonymous access while it is disabled in IIS.

Why mostly MEX endpoint?

Because the default settings of mexHttpBinding allows anonymous access by setting clientCredentialsType to None. So if you have a mex endpoint and you are using out of the box mexHttpBinding you will be getting the above exception.

A simple fix is to use the same secured binding, in this case basicHttpBinding IMyService, for the mex endpoint as well or create a new binding and disable the anonymous access for mex endpoint as well.

Posted in WCF | 6 Comments »

Per Endpoint UserName Authentication

Posted by zamd on February 15, 2008

In this post I will explain an extensibility mechanism to support multiple userName/password validation modes in the same service. 

When you use UserName authentication in WCF there are couple of different mode for the actual UserName/Password validation. These modes are:

·         Windows: Credentials are verified against a windows account (either local or domain).

·         Custom: Credentials are verified by calling your custom UserNamePasswordValidator component.

·         Membership: Credentials are verified by using SqlMembershipProvider.

You can configure userName authentication and the actual validation mode using the following service behavior:

<serviceCredentials>

  <serviceCertificate findValue=01 0a 27 storeName=My x509FindType=FindByThumbprint/>

  <userNameAuthentication userNamePasswordValidationMode=Custom

                          customUserNamePasswordValidatorType=UserNameValidationSamples/>

</serviceCredentials>

Using this behavior however will results in the same validation mode (custom in above case) being used for all the endpoints. Sometimes there is a requirement to support different mode of UserName/Password validation for different endpoints belonging to the same service. Out of the box WCF doesn’t provide this functionality so I have created a custom endpoint behavior and a behavior extension to achieve this functionality.

The implementation of my custom behavior clones the ServiceCredentials behavior and overrides the value of userNamePasswordValidationMode with the endpoint’s mode value.

namespace UserNameValidationSample

{

    //behavior configuration extension element

    public class UserNameValidationBehaviorElement : BehaviorExtensionElement

    {

        public UserNameValidationBehaviorElement()

        {

        }

        public override Type BehaviorType

        {

            get { return typeof(UserNameValidationBehavior); }

        }

        protected override object CreateBehavior()

        {

            return new UserNameValidationBehavior(this.Mode);

        }

        [ConfigurationProperty(“mode”)]

        public UserNamePasswordValidationMode Mode

        {

            get

            {

                return (UserNamePasswordValidationMode)base[“mode”];

            }

            set

            {

                base[“mode”] = value;

            }

        }

        ConfigurationPropertyCollection properties = null;

        protected override ConfigurationPropertyCollection Properties

        {

            get

            {

                if (this.properties == null)

                {

                    ConfigurationPropertyCollection propertys = new ConfigurationPropertyCollection();

                    propertys.Add(

                                    new ConfigurationProperty(“mode”, typeof(UserNamePasswordValidationMode), null,

                                                                              ConfigurationPropertyOptions.IsRequired));

                    this.properties = propertys;

                }

                return this.properties;

            }

        } 

    }

    public class UserNameValidationBehavior : IEndpointBehavior

    {

        UserNamePasswordValidationMode mode;

        public UserNameValidationBehavior(UserNamePasswordValidationMode mode)

        {

            mode = mode;

        }

        #region IEndpointBehavior Members

 

        public void AddBindingParameters(ServiceEndpoint endpoint,

                System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

        {

            // override the validation mode for this endpoint. 

            var sc = bindingParameters.Remove<ServiceCredentials>();

            if (sc != null)

            {

                var scCopy = sc.Clone();

                scCopy.UserNameAuthentication.UserNamePasswordValidationMode = mode; 

                bindingParameters.Add(scCopy);

            }

        } 

        public void ApplyClientBehavior(ServiceEndpoint endpoint,

                               System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

        {} 

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint,

                 System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

        {} 

        public void Validate(ServiceEndpoint endpoint)

        {} 

        #endregion

    }

}

This is how you define and use a the behavior from config file:

<system.serviceModel>

  <services>

    <service name=UserNameValidationSamples.CalculatorService behaviorConfiguration=credBehavior>

      <endpoint address=http://localhost:8080/CalculatorService/Custom

                binding=wsHttpBinding

                bindingConfiguration=noSecureConversation

                contract=UserNameValidationSamples.ICalculatorService

                behaviorConfiguration=customValidation

                />

      <endpoint address=http://localhost:8080/CalculatorService/Windows

                binding=wsHttpBinding

                bindingConfiguration=noSecureConversation

                contract=UserNameValidationSamples.ICalculatorService

                behaviorConfiguration=windowsValidation

                />

    </service>

  </services> 

  <behaviors>

    <endpointBehaviors>

      <!– my custom behavior –>

      <behavior name=customValidation>

        <userNameValidation mode=Custom/>

        <!– Custom, Windows, Membership–>

      </behavior> 

      <behavior name=windowsValidation>

        <userNameValidation mode=Windows/>

        <!– Custom, Windows, Membership–>

      </behavior> 

    </endpointBehaviors>

  </behaviors> 

  <!– create a userNameValidation extension –>

  <extensions>

    <behaviorExtensions>

      <add name=userNameValidation type=UserNameValidationSamples.UserNameValidationBehaviorElement/>

    </behaviorExtensions>

  </extensions>

</system.serviceModel>

Source code of a VS2008 project is attached with this post.

Download: usernamesamples.zip

Posted in WCF | 2 Comments »

Message security knobs

Posted by zamd on February 11, 2008

Security in WCF is all about credentials. Credentials are used for authentication; claims extracted from the credentials are used for authorization. If credential contains keys then these are used to provide integrity and confidentiality. 

Credentials are supported both at transport level and message level. For message level credentials, WS-Security specification defines the mechanism to encapsulate security token (serialized representation of credentials) in a SOAP message. 

When you use message security with WCF there are couple of interesting knobs which I am going to explain in this post. So let’s consider the following snippet as an example. 

<message clientCredentialType=UserName 

         establishSecurityContext=false 

         negotiateServiceCredential=false 

         algorithmSuite=Default/> 

·         establishSecurityContext 

Setting establishSecurityContext=false results in one shot message security. In this mode every message is secured independently — algorithm suits determines what algorithm should be used to secure the message. By default WCF uses RSA-OAEP, which uses a symmetric key to encrypt the message and signature. This symmetric key is then wrapped/transported using the public key from the server certificate. All of this security stuff is contained in every SOAP message. 

With one shot message security there are further two options: 

o   Not using derived keys 

Above explanation was for case in which derived keys were turned off. Some of the other stacks (e.g IBM DataPower) don’t support derived keys yet so in those cases this needs to be turned off. By default wsHttpBinding uses the derived keys and there is no way to turn this off from the config file. You have to use a custom binding, if you need to turn off derived keys. See this for details. By default “derived keys” are turned off in case of basicHttpBinding. 

o   Using derived keys 

With derived keys turned on, WCF derives two keys from the symmetric key and use one to sign the SOAP message and other to encrypt various parts of the SOAP message. It is considered bad practice to sign and encrypt data using the same key as certain attacks are more likely to succeed in this case so derived keys provide more resilient against such attacks and that’s why its enabled on wsHttpBinding as a default option. 

Setting establishSecurityContext=true results in a “Security Context Token” established between client and server. Once this token is created on both ends – all subsequent message exchanges will be secured using this context token. By default this token is issued with a 15 minute life time and need to be re-issued if required beyond 15 minutes. Again not using derived keys here means multiple messages (exchanged in 15 minutes life-span) will be secured using the same “Security Context Token” so security in this case will be more weaker than one shot security. So use of derived keys is more important in case of secure conversation. 

·         negotiateServiceCredential 

Credential negotiation is a process of exchanging keys and authenticating communicating parties using some form of handshake. Now credential negotiate can be done at the transport level using something like SSL over HTTPS or can be done at SOAP level using TLSNego (SSL over SOAP). 

Setting negotiateServiceCredential=falsemeans that service credentials should be made available to the client using some out-of-band mechanism. Here starts the complexity as WCF supports many different types of credentials and out-of-band availability mechanism is credential specific. 

So in case of Certificate credentials, service certificate should be provided to all the clients prior to communication and clients should refer the service certificate in their security configuration. 

<clientCredentials> 

  <serviceCertificate> 

    <defaultCertificate findValue=localhost 

      storeLocation=LocalMachine storeName=My 

      x509FindType=FindBySubjectName/> 

    <authentication certificateValidationMode=PeerOrChainTrust /> 

  </serviceCertificate> 

</clientCredentials> 

In case of Kerberos credentials, setting negotiateServiceCredential=false results in on-shot Kerberos or sometimes called Kerberos direct. For this mode to work the service must be running under machine SPN (NetworkService, LocalService accounts etc) and client must specify the SPN in the endpoint identity. 

<endpoint address=http://zamd.net/servicemodelsamples/service.svc 

          binding=customBinding 

          bindingConfiguration=Binding1 

          behaviorConfiguration=ClientCredentialsBehavior 

          contract=Microsoft.ServiceModel.Samples.ICalculator > 

  <identity> 

    <servicePrincipalName value=host/zamd.net/> 

  </identity> 

</endpoint> 

Setting negotiateServiceCredential=true will results in credentials negotiation. Now as mentioned earlier actual negotiation depends on client and service credential type and could either be done at transport level or message level (using appropriate credential exchange protocols) depending on your security mode. Let’s take this example: 

<wsHttpBinding> 

  <binding name=Binding1> 

    <security mode=Message> 

      <message clientCredentialType=UserName negotiateServiceCredential=true/> 

    </security> 

  </binding> 

</wsHttpBinding> 

The above binding will result in UserNameForSslNegotiated credential type — which uses UserName as client credential type and certificate as service credential and service credentials will be negotiated using SSL over SOAP aka TLSNEGO. 

Posted in WCF | 6 Comments »

My MSDN Flash Article

Posted by zamd on February 10, 2008

My WMI article is published in UK MSDN flash.

In this article I briefly explained WMI.net Provider extensions introduced in .net Framework V3.5.

 

Posted in .net | Leave a Comment »

Setting ProtectionLevel from config file

Posted by zamd on February 10, 2008

Protectionlevel enum defines the level of security in terms of encryption & signature. When programing at the Service Model layer, ProtectionLevel can be set at various levels:

·         ServiceContract level: all messages/faults of a service contract will have same protection level

·         OperationContract level: An operation can override the protection level specified at the contract level. So messages/faults of an operation can have different protection requirements.

·         MessageContract level: Individual messages/faults can also specify their own protection level, overriding the one specified at higher level.

If your only requirement is to be able to set protection level from config file, then a simple option could be to access the description object model and update the contract protection level there before opening the service host or proxy.

ServiceHost svc = new ServiceHost(typeof(CalculatorService));

svc.Description.Endpoints[0].Contract.ProtectionLevel = GetProtectionLevelFromConfig();

If however, you want to set different protection level for different endpoints, then you have to do some more work.

Specifically you have to create an endpoint behavior, from which you will access the ChannelProtectionRequirements parameter to specify endpoint specific protection requirements. Here is step by step procedure to do this:

1.       Create an endpoint behavior and add following code to AddBindingParameters method.

    public class ProtectionLevelBehavior : IEndpointBehavior

    {

        ProtectionLevel level;

 

        internal ProtectionLevelBehavior(ProtectionLevel level)

        {

            this.level = level;

        }

        #region IEndpointBehavior Members

 

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

        {

            var proReq =

                bindingParameters.Remove<ChannelProtectionRequirements>();

            proReq = new ChannelProtectionRequirements();

            MessagePartSpecification unProtectedSpec = new MessagePartSpecification();

            MessagePartSpecification protectedSpec = new MessagePartSpecification(true);

            //I’m setting same protection level for all the actions.

            // You could specify different protection level per action, if required.

            // Also note, I haven’t implemented any support for custom SOAP headers.

            // However that can easily be added using the same mechansim.

            switch (level)

            {

                case ProtectionLevel.None:

                    proReq.OutgoingSignatureParts.AddParts(unProtectedSpec, “*”);

                    proReq.IncomingSignatureParts.AddParts(unProtectedSpec, “*”);

                    proReq.OutgoingEncryptionParts.AddParts(unProtectedSpec, “*”);

                    proReq.IncomingEncryptionParts.AddParts(unProtectedSpec, “*”);

                    break;

                case ProtectionLevel.Sign:

                    proReq.OutgoingSignatureParts.AddParts(protectedSpec, “*”);

                    proReq.IncomingSignatureParts.AddParts(protectedSpec, “*”);

                    proReq.OutgoingEncryptionParts.AddParts(unProtectedSpec, “*”);

                    proReq.IncomingEncryptionParts.AddParts(unProtectedSpec, “*”);

                    break;

                case ProtectionLevel.EncryptAndSign:

                    proReq.OutgoingSignatureParts.AddParts(protectedSpec, “*”);

                    proReq.IncomingSignatureParts.AddParts(protectedSpec, “*”);

                    proReq.OutgoingEncryptionParts.AddParts(protectedSpec, “*”);

                    proReq.IncomingEncryptionParts.AddParts(protectedSpec, “*”);

                    break;

            }

            // Add our protection requirement for this endpoint into the binding params.

            bindingParameters.Add(proReq);

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

        {

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

        {

        }

        public void Validate(ServiceEndpoint endpoint)

        {

        }

        #endregion

    }

2.       Now create a behavior extension so that this behavior can be enabled/disabled using configuration file. The behavior extension will read the configured protectionLevel from config file and will create an instance of above endpoint behavior to plug it into behavior collections.

    //behavior configuration extension element

        public class ProtectionLevelBehaviorElement : BehaviorExtensionElement

        {

            public ProtectionLevelBehaviorElement()

            {

            }

            public override Type BehaviorType

            {

                get { return typeof(ProtectionLevelBehavior); }

            }

 

            protected override object CreateBehavior()

            {

                return new ProtectionLevelBehavior(this.Level);

            }

            [ConfigurationProperty(“level”)]

            public ProtectionLevel Level

            {

                get

                {

                    return (ProtectionLevel)base[“level”];

                }

                set

                {

                    base[“level”] = value;

                }

            }

            ConfigurationPropertyCollection properties = null;

            protected override ConfigurationPropertyCollection Properties

            {

                get

                {

                    if (this.properties == null)

                    {

                        ConfigurationPropertyCollection propertys = new ConfigurationPropertyCollection();

                        propertys.Add(new ConfigurationProperty(“level”, typeof(ProtectionLevel), null, ConfigurationPropertyOptions.IsRequired));

                        this.properties = propertys;

                    }

                    return this.properties;

                }

            }

        }

3.      And this is how you will specify the protection level from config file using the above behavior extension.

  <behaviors>

    <endpointBehaviors>

      <behavior name=endpointSecurityConfig>

        <protectionLevel level=Sign/>

        <!– None, Sign, EncryptAndSign–>

      </behavior>

    </endpointBehaviors>

  </behaviors>

I have attached the source code with this post. Feel free to download and reuse.

Download: protectionlevelsample.zip

Posted in WCF | 1 Comment »

Changing MessageProtectionOrder for Built-in bindings

Posted by zamd on February 10, 2008

MessageProtectionOrder enumeration defines the order of encryption and signing for the SOAP messages. WCF could be configured to first sign messages and then encrypt or other way around. 

All the built-in bindings (basicHttpBinding, wsHttpBinding etc) uses a default protection order and won’t let you change it. The only way to change the protection order is to use a custom binding(<message> element). However you might end up in a situation where you have configured all sorts of settings on a built-in binding and now you want to alter the protection order (or any other setting not directly exposed through the built-in binding). Following steps and code snipped shows how to create a custom binding to override a property value while still retaining the original settings of the binding/elements. 

·         Ask the configured binding to create all the binding elements for you (as configured in config file). 

·         Find the required BindingElement, which exposing the property you need to change (AsymmetricSecurityBindingElement in this case). 

·         Overwrite the current value with your desired value. You could also pick the actual value from the config file. 

·         Now create a CustomBinding object and copy updated binding element collection into this new object. 

·         Set the custom binding as new binding for the endpoint.  

BindingElementCollection col = fac.Endpoint.Binding.CreateBindingElements();  

AsymmetricSecurityBindingElement asbe = col.Find<AsymmetricSecurityBindingElement>(); 

asbe.MessageProtectionOrder = MessageProtectionOrder.EncryptBeforeSign; 

fac.Endpoint.Binding = new CustomBinding(col); 

Note: You have the flexibility to make the change on a per endpoint basis rather for the whole binding; it all depends on your requirements. 

In the next post, I will talk about ProtectionLevel attribute and how to make it config enabled. 

  

Stay tuned… 

Posted in WCF | 1 Comment »

 
Follow

Get every new post delivered to your Inbox.