title: WCF and Kerberos Authentication
body: <p>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.</p>
  
  <p><strong>Setup</strong></p>
  
  <p>I have the WCF service in an IIS website on a remote machine</p>
  
  <ul>
  <li>IIS 6.0 on Windows 2003 R2 - SP 2</li>
  <li>The SPN for the machine has been added (http/myserver &amp;&amp; http/myserver:8080)</li>
  <li>An AD account has been created for the IIS app pool</li>
  <li>The AD account has the setting, allow delegation (for Kerberos), set to true</li>
  </ul>
  
  <p>I am using <a href="http://blogs.iis.net/brian-murphy-booth/archive/2007/03/09/delegconfig-delegation-configuration-reporting-tool.aspx" rel="nofollow noreferrer">Brian Booth's debug site</a> on 8080 and the site passes all requirements for Kerberos delegation.  The debug IIS site has anonymous authentication off, and Integrated Windows authentication on.</p>
  
  <p>I have mirrored these settings to the site hosting the WCF service.</p>
  
  <p><strong>Web Service - Web Config (Original)</strong></p>
  
  <pre><code>&lt;system.serviceModel&gt;
      &lt;bindings&gt;
          &lt;wsHttpBinding&gt;
              &lt;binding name="WsHttpBindingConfig"&gt;
                  &lt;security&gt;
                      &lt;message negotiateServiceCredential="true" /&gt;
                  &lt;/security&gt;
              &lt;/binding&gt;
          &lt;/wsHttpBinding&gt;
      &lt;/bindings&gt; 
      &lt;services&gt;
          &lt;service behaviorConfiguration="ServiceBehavior" name="Service"&gt;    
              &lt;endpoint address="" 
                  binding="wsHttpBinding" 
                  bindingConfiguration="WsHttpBindingConfig" 
                  contract="IService"&gt;    
                  &lt;identity&gt;    
                      &lt;servicePrincipalName value="http/myserver" /&gt;    
                      &lt;dns value="" /&gt;    
                  &lt;/identity&gt;    
              &lt;/endpoint&gt;    
              &lt;endpoint address="mex" 
                  binding="mexHttpBinding" 
                  contract="IMetadataExchange" /&gt;    
          &lt;/service&gt;    
      &lt;/services&gt;    
      &lt;behaviors&gt;    
          &lt;serviceBehaviors&gt;    
              &lt;behavior name="ServiceBehavior"&gt;    
                  &lt;serviceMetadata httpGetEnabled="true"/&gt;    
                  &lt;serviceDebug includeExceptionDetailInFaults="true"/&gt;    
                  &lt;serviceAuthorization 
                      impersonateCallerForAllOperations="true" /&gt;    
              &lt;/behavior&gt;    
          &lt;/serviceBehaviors&gt;    
      &lt;/behaviors&gt;    
  &lt;/system.serviceModel&gt;
  </code></pre>
  
  <p><strong>Web Service - Web Method</strong></p>
  
  <pre><code>[OperationBehavior(Impersonation = ImpersonationOption.Required)]
  public string GetCurrentUserName()
  {
      string name = WindowsIdentity.GetCurrent().Name;
      return name;
  }
  </code></pre>
  
  <p><strong>Client App - App Config</strong></p>
  
  <pre><code>&lt;system.serviceModel&gt;
      &lt;bindings&gt;
          &lt;wsHttpBinding&gt;
              &lt;binding name="WSHttpBinding_IService" 
                  ... /&gt;
                  ...
                  &lt;security mode="Message"&gt;
                      &lt;transport clientCredentialType="Windows" 
                          proxyCredentialType="None" 
                          realm="" /&gt;
                      &lt;message clientCredentialType="Windows" 
                          negotiateServiceCredential="true"
                          algorithmSuite="Default" 
                          establishSecurityContext="true" /&gt;
                  &lt;/security&gt;
              &lt;/binding&gt;
          &lt;/wsHttpBinding&gt;
      &lt;/bindings&gt;
      &lt;client&gt;
          &lt;endpoint address="http://myserver/Service.svc" 
              binding="wsHttpBinding" 
              bindingConfiguration="WSHttpBinding_IService"
              contract="KerberosService.IService" 
              name="WSHttpBinding_IService"&gt;
              &lt;identity&gt;
                  &lt;servicePrincipalName value="http/myserver" /&gt;
              &lt;/identity&gt;
          &lt;/endpoint&gt;
       &lt;/client&gt;
  &lt;/system.serviceModel&gt;
  </code></pre>
  
  <p><strong>Application Error</strong></p>
  
  <p>The following error occurs when my test application, a WinForms app, tries to call the web method:</p>
  
  <blockquote>
    <p>"The HTTP request is unauthorized with
    client authentication scheme
    'Anonymous'. The authentication header
    received from the server was
    'Negotiate,NTLM'."</p>
  </blockquote>
  
  <p><strong>Event Log</strong></p>
  
  <p>The following error is in the event log:</p>
  
  <blockquote>
    <p>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.</p>
  </blockquote>
  
  <p>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.</p>
  
  <p>How should I configure this WCF service for Kerberos authentication and delegation?</p>
  
  <p><strong>Revision 1</strong></p>
  
  <p>After reading <a href="https://stackoverflow.com/questions/1026855/wcf-windows-authentication-security-settings-require-anonymous">this SO question</a> I removed the metadata endpoint.  This has not resolved the issue.</p>
  
  <p><strong>Revision 2</strong></p>
  
  <p>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.</p>
  
  <p><strong>Web Service - Web Config (Revised)</strong></p>
  
  <pre><code>&lt;basicHttpBinding&gt;
      &lt;binding name="basicBindingConfig"&gt;
          &lt;security mode="TransportCredentialOnly"&gt;
              &lt;transport clientCredentialType="Windows" 
                  proxyCredentialType="Windows" 
                  realm="" /&gt;
          &lt;/security&gt;
      &lt;/binding&gt;
  &lt;/basicHttpBinding&gt;
  </code></pre>
  
  <p><strong>Client App - App Config (Revised)</strong></p>
  
  <pre><code>&lt;!-- ... --&gt;
  &lt;security mode="TransportCredentialOnly"&gt;
      &lt;transport clientCredentialType="Windows" 
          proxyCredentialType="Windows"
          realm="" /&gt;
      &lt;message clientCredentialType="UserName" 
          algorithmSuite="Default" /&gt;
  &lt;/security&gt;
  &lt;!-- ... --&gt;
  </code></pre>
  
  <p><strong>Error (Revised)</strong></p>
  
  <p>The current error looks like it contains a Kerberos authentication header.</p>
  
  <blockquote>
    <p>The HTTP request is unauthorized with
    client authentication scheme
    'Negotiate'. The authentication header
    received from the server was
    'Negotiate SOMEHUGESCARYKEYHERE</p>
  </blockquote>