Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IIS Hosted WCF Service & SQL Queries Using Windows Authentication

I'm fairly new to WCF but I have a WCF Service hosted in IIS that has several queries to our SQL Server. I am consuming the WCF service with a WPF application. What I'm trying to do is allow windows authentication to pass from the WPF Client, To The WCF Service, To The SQL Server so that the SQL Queries are executed as the clients user. I've been trying to configure the website and host in various ways with no luck so far.

On my WCF Service website, I have Anonymous Authentication=true(for MEX), ASP.NET Impersonation=true and Windows Authentication=true.

In my WCF Service Web.config:

<configuration>
  <system.web>
    <customErrors mode="Off"/>
    <authentication mode="Windows"/>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </assemblies>
    </compilation>
  </system.web>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding maxReceivedMessageSize="5000000" name="WindowsSecurity">
          <readerQuotas maxDepth="200"/>
          <security mode="Transport">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="ADATrackingService" behaviorConfiguration="ServiceBehavior">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="WindowsSecurity"
          name="wsHttpEndpoint" contract="IADATrackingService" />
        <endpoint address="mex" binding="mexHttpsBinding" name="MexHttpsBindingEndpoint"
          contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization impersonateCallerForAllOperations="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
  <connectionStrings>
    <add name="ADATrackingEntities" connectionString="metadata=res://*/EntityModel.ADATrackingModel.csdl|res://*/EntityModel.ADATrackingModel.ssdl|res://*/EntityModel.ADATrackingModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=MYSERVER;initial catalog=ADATracking;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

Then in my WPF client App.Config I have:

<configuration>
    <system.serviceModel>
      <behaviors>
        <endpointBehaviors>
          <behavior name="WindowsAuthentication">
            <clientCredentials>
              <windows allowedImpersonationLevel="Delegation"/>
            </clientCredentials>
          </behavior>
        </endpointBehaviors>
      </behaviors>
        <bindings>
            <wsHttpBinding>
                <binding name="wsHttpEndpoint" 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="5000000"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="200" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Transport">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://MyService.svc"
                binding="wsHttpBinding" behaviorConfiguration="WindowsAuthentication" bindingConfiguration="wsHttpEndpoint"
                contract="ADATrackingService.IADATrackingService" name="wsHttpEndpoint">
                <identity>
                    <servicePrincipalName value="host/MyServer.com" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

My service calls are just returning simple queries from SQL using the metadata for allowing impersonation. Every time I run the client and call something from my service i'm just getting an error opening the data connection for "NT Authority/ANONYMOUS LOGIN" even with AnonymousAuthentication=false set in IIS??? Any help would be greatly appreciated. Thanks!

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public List<IndividualDisability> GetIndividualDisabilities()
{
    WindowsIdentity callerWindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity;
    if (callerWindowsIdentity == null)
    {
        throw new InvalidOperationException
         ("The caller cannot be mapped to a Windows identity.");
    }
    using (callerWindowsIdentity.Impersonate())
    {
        using (var context = new ADATrackingEntities())
        {
            return context.IndividualDisabilities.OfType<IndividualDisability>().Include("ADACode").Include("Individual").Include("Disability").ToList();
        }
    }
}
like image 734
ccorrin Avatar asked Jan 23 '12 20:01

ccorrin


1 Answers

Well, after browsing around some more today. I've finally got it working! The issue was that in active directory, I needed to allow Delegation to the SQL Server box. There is a setting in AD that you have to set on the web server box to allow it to delegate to the SQl Service on your SQl Server box on port 1433. I also had to make sure I was setup for kerebos authentication on the webserver. This blog post explained my situation exactly and helped me get it working from start to finish:

ASP.Net Impersonation

like image 104
ccorrin Avatar answered Oct 25 '22 02:10

ccorrin