I've inherited a WCF web service that uses impersonation to connect to the database, while trying to get the automated tests running I noticed that any of these hitting the test instance of the service were failing with a 401 response.
Using Fiddler to capture the response I was able to see that it was trying to open the database connection using NT AUTHORITY\ANONYMOUS LOGON
.
I eventually got remote debugging setup and break pointed immediately before the connection was opened and I used the immediate window to check the current principal, here are the results:
?System.Security.Principal.WindowsIdentity.GetCurrent().Name
"myDomain\myUser"
This is exactly as I was expecting to see. Following this I checked the content of our connection string and it was:
Data Source=myDbServer;Initial Catalog=devDb;Integrated Security=True;User ID=;Password=;Asynchronous Processing=False;Connect Timeout=300;Application Name=myApp
Which again is what was expected.
My next step was to disable the impersonation and see what user was trying to connect at that point:
?System.Security.Principal.WindowsIdentity.GetCurrent().Name
"NT AUTHORITY\NETWORK SERVICE"
However this time the 401 error reported that the user myDomain\myDevServer
did not have permissions.
The service is running under Network Service on IIS 7, and this is as intended. Though I did try having it run under a domain user, but saw the exact same results: SQL attempting login with NT AUTHORITY\ANONYMOUS LOGON
My issue is closely related to the one experienced on this question. However using the same immediate window technique I verified my impersonation level, which was indeed delegation:
?System.Security.Principal.WindowsIdentity.GetCurrent().ImpersonationLevel
Delegation {4}
So what would cause the trusted sql connection to be getting a completely different user than what is shown in the current principal?
Update:
I have verified the settings on the DC, the machine account is configured for unconstrained delegation, and my user account is not marked sensitive.
I also stepped through this article I did note that under the double hop section he says that the ASP.NET Impersonation authentication provider should be enabled, however doing so causes the server to immediately return a 500, it never makes it into managed code.
Additional information:
The services all have the [OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
attribute applied to them and the web.config file has <serviceAuthorization impersonateCallerForAllOperations="true" />
The services have both a webHttpBinding for restful calls and a basicHttpBinding for soap calls, both endpoints experience the same issue.
Attempting to authenticate to a remote resource under an impersonated context requires delegation. Follow the Delegation guidelines from Delegation and Impersonation with WCF (these steps require a domain administrator):
On the domain controller, clear the Account is sensitive and cannot be delegated check box for the account under which the client application is running.
On the domain controller, select the Account is trusted for delegation check box for the account under which the client application is running.
On the domain controller, configure the middle tier computer so that it is trusted for delegation, by clicking the Trust computer for delegation option.
On the domain controller, configure the middle tier computer to use constrained delegation, by clicking the Trust this computer for delegation to specified services only option.
If you're under a Windows Server 2012 environment is somehow easier, see How Windows Server 2012 Eases the Pain of Kerberos Constrained Delegation.
If you want to learn more about this problem, google for "Kerberos double hop" and you'll find a tonne of resources, including many answers here on SO.
The most likely cause is a misconfigured SQL Service Principal Name (SPN). When connecting directly to SQL (eg. from Management Studio) a misconfigured SPN causes a fallback to NTLM (ie. it won't be noticed). But in delegation case fallback is not allowed and this causes authentication to fail, so the authorization is done against the anonymous logon, exactly as seen in the OP. SQL Server Kerberos and SPN Quick Reference is a good resource.