Tuesday, February 9, 2010

WCF BasicHttpBinding and windows authentication on IIS 6.0

Recently I tried to host a WCF service on IIS 6.0 with basic http binding.
I needed to authenticate users with windows security mode.

I configured the WCF binding like below in the web.config file:

<bindings>
<basicHttpBinding>
<binding name="BasicHttpWindowsBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>


Although I configured IIS so that anonymous authentication is not allowed and windows authentication is required, I got this error when I opened the service page with internet explorer:

System.NotSupportedException: security settings for this service require windows authentication but it is not enabled for the iis application that hosts this service

Well, it was disappointing because both service configuration and the IIS configuration was configured for windows authentication mode.

After a little struggle I found that basicHttpBinding's windows authentication is not supported by IIS 6.0.
Instead security mode of the binding should be set to Ntlm and you have to allow anonymous authentication in the IIS site settings.

Here is the complete config file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<system.web>
<compilation debug="true" />
<customErrors mode="Off" />
<authentication mode="Windows">
</authentication>
<authorization>
<allow users="somedomain\someuser"/>
<deny users="*"/>
</authorization>
</system.web>

<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5" />
<providerOption name="WarnAsError" value="false" />
</compiler>
</compilers>
</system.codedom>

<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="SvcFile" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
<directoryBrowse enabled="true" showFlags="Date, Time, Size, Extension, LongDate" />
</system.webServer>

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpWindowsBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="SomeServiceBehavior" name="SomeAssembly.SomeService">
<endpoint binding="basicHttpBinding" bindingConfiguration="BasicHttpWindowsBinding" contract="SomeAssembly.ISomeService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost/SomeAssembly/ISomeService.svc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SomeServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

</configuration>