WCF and Kerberos Authentication

I have followed numerous msdn articles and the codeplex guidance but cannot get WCF to work with Kerberos authentication and delegation and would appreciate a little help.

Setup

I have the WCF service in an IIS website on a remote machine

  • IIS 6.0 on Windows 2003 R2 – SP 2
  • The SPN for the machine has been added (http/myserver && http/myserver:8080)
  • An AD account has been created for the IIS app pool
  • The AD account has the setting, allow delegation (for Kerberos), set to true

I am using Brian Booth’s debug site on 8080 and the site passes all requirements for Kerberos delegation. The debug IIS site has anonymous authentication off, and Integrated Windows authentication on.

I have mirrored these settings to the site hosting the WCF service.

Web Service – Web Config (Original)

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WsHttpBindingConfig">
                <security>
                    <message negotiateServiceCredential="true" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings> 
    <services>
        <service behaviorConfiguration="ServiceBehavior" name="Service">    
            <endpoint address="" 
                binding="wsHttpBinding" 
                bindingConfiguration="WsHttpBindingConfig" 
                contract="IService">    
                <identity>    
                    <servicePrincipalName value="http/myserver" />    
                    <dns value="" />    
                </identity>    
            </endpoint>    
            <endpoint address="mex" 
                binding="mexHttpBinding" 
                contract="IMetadataExchange" />    
        </service>    
    </services>    
    <behaviors>    
        <serviceBehaviors>    
            <behavior name="ServiceBehavior">    
                <serviceMetadata httpGetEnabled="true"/>    
                <serviceDebug includeExceptionDetailInFaults="true"/>    
                <serviceAuthorization 
                    impersonateCallerForAllOperations="true" />    
            </behavior>    
        </serviceBehaviors>    
    </behaviors>    
</system.serviceModel>

Web Service – Web Method

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetCurrentUserName()
{
    string name = WindowsIdentity.GetCurrent().Name;
    return name;
}

Client App – App Config

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WSHttpBinding_IService" 
                ... />
                ...
                <security mode="Message">
                    <transport clientCredentialType="Windows" 
                        proxyCredentialType="None" 
                        realm="" />
                    <message clientCredentialType="Windows" 
                        negotiateServiceCredential="true"
                        algorithmSuite="Default" 
                        establishSecurityContext="true" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://myserver/Service.svc" 
            binding="wsHttpBinding" 
            bindingConfiguration="WSHttpBinding_IService"
            contract="KerberosService.IService" 
            name="WSHttpBinding_IService">
            <identity>
                <servicePrincipalName value="http/myserver" />
            </identity>
        </endpoint>
     </client>
</system.serviceModel>

Application Error

The following error occurs when my test application, a WinForms app, tries to call the web method:

“The HTTP request is unauthorized with client authentication scheme ‘Anonymous’. The authentication header received from the server was ‘Negotiate,NTLM’.”

Event Log

The following error is in the event log:

Exception: System.ServiceModel.ServiceActivationException: The service ‘/Service.svc’ cannot be activated due to an exception during compilation. The exception message is: Security settings for this service require ‘Anonymous’ Authentication but it is not enabled for the IIS application that hosts this service.

Which I don’t understand. The whole point of this service is to not allow anonymous authentication, every user/request must be authenticated using Kerberos tickets, then passing them through to other machines.

How should I configure this WCF service for Kerberos authentication and delegation?

Revision 1

After reading this SO question I removed the metadata endpoint. This has not resolved the issue.

Revision 2

After more researching I found a few posts suggesting to change wsHttpBinding to basicHttpBinding. The modification to that portion of the web.config has been included below, and the service endpoint has been updated to refer to that binding.

Web Service – Web Config (Revised)

<basicHttpBinding>
    <binding name="basicBindingConfig">
        <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" 
                proxyCredentialType="Windows" 
                realm="" />
        </security>
    </binding>
</basicHttpBinding>

Client App – App Config (Revised)

<!-- ... -->
<security mode="TransportCredentialOnly">
    <transport clientCredentialType="Windows" 
        proxyCredentialType="Windows"
        realm="" />
    <message clientCredentialType="UserName" 
        algorithmSuite="Default" />
</security>
<!-- ... -->

Error (Revised)

The current error looks like it contains a Kerberos authentication header.

The HTTP request is unauthorized with client authentication scheme ‘Negotiate’. The authentication header received from the server was ‘Negotiate SOMEHUGESCARYKEYHERE

WCF authentication via Kerberos on Windows XP

I have got a .NET WCF client talking to a Java server component. Server-side authentication is done via an intermediate Apache server that is configured as a reverse proxy. The .NET client has a confi

kerberos authentication in Windows 7

I have to implement Kerberos-based Windows authentication in WCF. I am using Windows 7 Professional. I searched a lot but did not get any relevant article on this topic. How can I implement Kerberos-

Mixed authentication modes: send both Kerberos token and username token over HTTPs with WCF

Is it possible to send both username token and the kerberos token over HTTPs with WCF? We are able to use custom binding with authentication mode set to ‘UserNameOverTransport’, which will include a u

WCF Custom Delegation/Authentication without Kerberos

I’m building a simple WCF service, probably exposed via HTTPS, using NTLM security. Since not all users are going to be capable of using the service directly, we’re writing a simple web front-end for

Kerberos authentication on iPhone

Are there any libraries for kerberos authentication for iPhone? Heimdal doesn’t have a build for iOS. Are there any examples for using Kerberos to Authenticate to Active Directory server?

Kerberos Authentication keytab KVNO

I have a network environment where kerberos authentication is setup in corporate standard (i.e. passoword can live only 30days for user). I’ve installed my java web application on this system which us

Kerberos authentication with SSPI

Note: I manage to make some progress, see the edit for my current question, thanks. I would like to use libcurl on Windows to access websites with a Kerberos/GSSAPI authentication. I first tried to wo

Optional SPNEGO Kerberos authentication

Is it possible to do optional kerberos authentication? What I want is: if the client (browser) is not on the domain it is redirected to a username/password web login. Otherwise it will do SPNEGO do K

Optional kerberos authentication?

Is it possible to do optional kerberos authentication? What I want is: if the client (browser) is not on the domain it is redirected to a username/password web login. Otherwise it will do SPNEGO do Ke

WCF – Why netTCPBinding works fine with Kerberos authentication without any SPN setting?

In one of our networks we are utilizing the netTCPBinding. The WCF service hosted in windows service that run as a domain account. From the event viewer I can see that my WCF service uses Kerberos au

Answers

Something that I notice: the client and server config don’t seem to agree on security mode.

In the original section, you have <security>….. in the web.config (omitted the mode=”message”), and <security mode=”Message”> on the client side.

After your edit, it seems that the client side is unchanged, but the server (web.config) now contains <security mode=”TransportCredentialOnly”>.

The question really is: can you guarantee that there’s only ever going to be one network leg between the client and the server being called? I.e. is this behind a corporate firewall? In that case, I would recommend netTcp binding with <security mode=”Transport”> on both ends.

If that’s not the case, then you’re ok with either wsHttpBinding (which supports more security and reliability features, but is slower and “heavier”) or basicHttpBinding. In that case, you would have to use <security mode=”Message”> on both ends, and authenticate the service with a certificate (so that the service and client have a common “secret” which to use for encryption).

I would try to leave out the impersonation parts out for the beginning and just get the basic communication and mutual authentication between service and client up and running first – once that’s in place, you can start adding the impersonation bits to it, and you can always fall back on a known configuration which works.

David Sackstein has a great series of blog posts explaining the five security scenarios that industry guru Juval Lowy has identified (in his Programming WCF book – the WCF Bible) as the most common and most useful – in order to limit the number of possible combinations of parameters you might want to tweak. One of them is a “Internet” scenario which would probably apply here, if your service is outward facing.

Marc

For me the current setup does work:

On the Server:

<system.serviceModel>
  <bindings>
    <wsHttpBinding>
      <binding name="wsHttpBindingConf" useDefaultWebProxy="true"/>
    </wsHttpBinding>
  </bindings>

  <services>
    <service behaviorConfiguration="returnFaults" name="Epze.BusinessLayer.ZeitManager">
        <endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConf" contract="Epze.Contract.IZeitManager"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
  </services>

  <behaviors>
    <serviceBehaviors>
        <behavior name="returnFaults">
            <serviceMetadata httpGetEnabled="true"/>
            <serviceDebug includeExceptionDetailInFaults="true"/>
            <serviceAuthorization impersonateCallerForAllOperations="true"/>
        </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Set the following attribute on all methods for the WCF:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]

On the Client:

<system.serviceModel>
  <bindings>
    <wsHttpBinding>
        <binding name="WSHttpBinding_IZeitManager" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
            <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
            <security mode="Message">
                <transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
                <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/>
            </security>
        </binding>
    </wsHttpBinding>
  </bindings>

  <behaviors>
    <endpointBehaviors>
        <behavior name="Delegation">
        <clientCredentials>
            <windows allowedImpersonationLevel="Delegation" />
        </clientCredentials>
        </behavior>
    </endpointBehaviors>
  </behaviors>        

  <client>
    <endpoint address="http://server.mydomain.net/ePZEsvc/ZeitManager.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IZeitManager" 
              contract="External.Epze.IZeitManager" name="WSHttpBinding_IZeitManager" behaviorConfiguration="Delegation">
        <identity>
            <servicePrincipalName value="HOST/localhost"/>
        </identity>                      
    </endpoint>
  </client>
</system.serviceModel>

HTH, Sven

You should try your initial configuration and make sure to set the IIS to be anonymous and windows authentication at the same time.The reason is when you are using wsHttpBinding default security is message security and there is no transport security defined unless you want to do https. SO Clr states that it needs anonymous authentication turned-on on the IIS.

You need to specify a behaviorConfiguration in your client config. SVCUtil does not auto generate. This resolved my issue and I am now successfully using Kerberos. It was a mission though!

<client>           
    <endpoint address="..."               
    binding="customBinding" bindingConfiguration="..."               
    contract="..." name="..."  behaviorConfiguration="ImpersonationBehavior" />                 
    </client>         
    <behaviors>
         <endpointBehaviors>            
         <behavior name="ImpersonationBehavior">               
              <clientCredentials>                 
              <windows allowedImpersonationLevel="Impersonation"/>                      </clientCredentials>             
    </behavior>                       
    </endpointBehaviors>                   
    </behaviors>