We have a .NET 3.5 Web Service (not WCF) running under IIS. It must use identity impersonate="true" and Integrated Windows authentication in order to authenticate to third-party software. In addition, it connects to a SQL Server database using ADO.NET and SQL Server Authentication (specifying a fixed User ID and Password in the connection string).
Everything worked fine until the database was moved from SQL Server A to SQL Server B. (Neither was the same as the web server.) Then the Web Service would throw the following exception:
A network-related or
instance-specific error occurred while
establishing a connection to SQL
Server. The server was not found or
was not accessible. Verify that the
instance name is correct and that SQL
Server is configured to allow remote
connections. (provider: Named Pipes
Provider, error: 40 – Could not open a
connection to SQL Server)
This error only occurs if identity impersonate is true in the Web.config.
Again, the connection string hasn’t changed and it specifies the user. I have tested the connection string and it works, both under the impersonated account and under the service account (and from both the remote machine and the server).
What needs to be changed to get this to work with impersonation?
EDIT:
Remus Rusanu pointed us in the right direction. It came down to Kerberos – the SPNs weren’t set up for the new server. See also asp.net via kerberos integrated windows authentication to sql server. Thank you!
When using impersonation and accessing a resource on a different host, delegation occurs (what the laymen call ‘two hops’). Since delegation is restricted by default, authentication fails, unless constrained delegation is explicitly enabled.
But wait, you says, I use SQL Authentication and SQL authentication is not an NTLM/Kerberos ‘resource’. True, says I, but you also use NAMED PIPES and named pipes are an NTLM/Kerberos resource, therefore delegation does occur.
See How to: Configure Client Protocols to make sure SQL Server is listening on TCP and Configuring Client Network Protocols for how to force the client to choose a specific protocol (ie. not try named pipe first). You can also force TCP by simply appending
tcp:in front of the server name in the connection string.