WCF Bindings with Kerberos Message Security

Message security and Kerberos seem to go hand in hand these days in the world of WCF. While Microsoft makes it particularly easy for you to secure a respective service under wsHttpBinding with Kerberos, I was unsure how do to this while running under SOAP 1.1. Thankfully, Microsoft gives us a very robust customBinding configuration solution for these cases when wsHttpBinding or basicHttpBinding just won’t do.

The customBinding and wsHttpBinding configurations for Kerberos are VERY similar, but do have a few subtle differences. Namely, the binding and bindingConfiguration. See below for the serviceModel configuration example for both SOAP 1.1 and SOAP 1.2.

<behaviors>
    <serviceBehaviors>   
        <behavior>
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>

        <behavior name="KerberosServiceBehavior">
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="false" />
            <serviceSecurityAudit auditLogLocation="Application"
                             suppressAuditFailure="true"
                             serviceAuthorizationAuditLevel="SuccessOrFailure"
                             messageAuthenticationAuditLevel="SuccessOrFailure" />
        </behavior>
    </serviceBehaviors>

</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
    <customBinding>
        <binding name="WsHttpSoap11Kerberos"  >
            <textMessageEncoding messageVersion="Soap11WSAddressing10" />
            <security authenticationMode="Kerberos" />
            <httpTransport/>
        </binding> 
    </customBinding>
    <wsHttpBinding>
        <binding name="KerberosServiceBinding"
              maxReceivedMessageSize="65536000">
            <readerQuotas maxDepth="2000000"
                     maxStringContentLength="2000000"
                     maxArrayLength="2000000"
                     maxBytesPerRead="2000000"
                     maxNameTableCharCount="2000000" />
            <security mode="Message">
                <message clientCredentialType="Windows"
                  negotiateServiceCredential="false"
                  establishSecurityContext="false" />
            </security>
        </binding>
    </wsHttpBinding>
</bindings>
<services>
    <service behaviorConfiguration="KerberosServiceBehavior"
              name="KerberosWcfService">
        <endpoint address="" binding="wsHttpBinding"
               bindingConfiguration="KerberosServiceBinding"
               contract="IKerberosWcfService">
            <identity>
                <dns value="localhost" />
                <servicePrincipalName value="HTTP/DOMAIN.COM DOMAINSERVICE_ACCOUNT" />
            </identity>
        </endpoint>
        <endpoint address="mex"
               binding="mexHttpBinding"
               contract="IMetadataExchange" />
    </service>
    <service behaviorConfiguration="KerberosServiceBehavior"
     name="KerberosSoap11WcfService">
        <endpoint address=""
    binding="customBinding"
    bindingConfiguration="WsHttpSoap11Kerberos"
    contract="IKerberosSoap11WcfService">
            <identity>
                <dns value="localhost" />
                <servicePrincipalName value="HTTP/DOMAIN.COM DOMAINSERVICE_ACCOUNT" />
            </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
</services> 

Practically, you would want to use the industry standard of wsHttpBinding with Kerberos and SOAP 1.2 if developing new WCF services. But if you have a dependency on SOAP 1.1, and need the ability to secure via Kerberos, this is your solution.