Wednesday, September 03, 2008

WCF web service setup with integrated security

I found setting up a WCF web service to use Windows integrated security to be a somewhat less-than-transparent process, so I thought I'd publish the steps I used to make it work.

Set IIS to allow Negotiate authentication in addition to NTLM

To do this, you need to find the web site identifier. In IIS 6.0, run IIS Manager and choose the Web Sites node and note the identifier of the web site that will host your web service:

Once done, drop to a command prompt and execute the following:
cscript C:\inetpub\AdminScripts adsutil.vbs GET w3svc/<identifier from above>/root/NTAuthenticationProviders
For example:
cscript C:\inetpub\AdminScripts adsutil.vbs GET w3svc/174926873/root/NTAuthenticationProviders

This will report output like the following:
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

NTAuthenticationProviders : (STRING) "Negotiate,NTLM"
If the NTAuthenticationProviders node reads "Negotiate,NTLM" you need make no changes. If it reads simply "NTLM" you must set it as follows:
cscript C:\inetpub\AdminScripts adsutil.vbs SET w3svc/<identifier from above>/root/NTAuthenticationProviders "Negotiate,NTLM"
Use at most one host header

There are workarounds, but out of the box you will get errors if you have more than one host header configured on the IIS web.

Set Windows integrated security, except for the .svc file


In IIS Manager's Directory Security tab for the web site (accessed via right-click | Properties), click Edit in the Authentication and access control section. At the web site level, Enable anonymous access should be unchecked and Integrated Windows authentication should be checked.

Now click on your web site to view its files. You should see the .svc file listed. Right-click this file and go to Properties:
This time, go to the File Security tab and click the Edit button in the Authentication and access control section. This file should have both anonymous access and integrated Windows authentication checked:
Use an integrated security binding

Lastly, you need to use an integrated security web service binding in web.config. Here is an example:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="IntegratedBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="true" />
<!--<serviceAuthorization impersonateCallerForAllOperations="true" />-->
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="My.Service.OrderService" behaviorConfiguration="serviceBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="IntegratedBinding" name="integratedBasicHttpEndpoint" contract="My.Service.IOrderService" />
<endpoint address="mex" binding="mexHttpBinding" name="mexEndpoint" contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
</system.serviceModel>

2 comments:

  1. We are having this exact same problem with the authentication headers. We are running a WCF service from a web application hosted on IIS, but it keeps coming back with "The remote server returned an error: (401) Unauthorized".

    If we make these changes, will it effect the website as a whole, or only the web application from which we are trying to host the WCF service from?

    V/R,
    T

    ReplyDelete
  2. The changes are specific to the website named by the identifier number you choose. Other webs with different identifiers won't be impacted.

    ReplyDelete