Reputation: 4823
I have an ASMX web service (on my localhost - WinXP IIS 5.1) that I call from a webclient. My webservice must consume another ASMX web service (on a Win 2003 server IIS 6.0).
When I provide credentials in my webservice code in a "hard-coded" manner:
engineWSE.Credentials = new System.Net.NetworkCredential("myUser", "myPass", "myDomain");
...the subsequent invoke of the remote web service works fine.
Now I am trying to impersonate myself in some initial testing. My initial reading on this tells me this can be a big subject but here is what I've done for starters:
UNCHECKED "Anonymous access" in my virtual directory for the WebClient site on my localhost
in web.config of my webclient site, I established: authentication mode="Windows" and identity impersonate="true"
in the webmethod of my webservice that has to call the remote service, I changed to:
engineWSE.Credentials = System.Net.CredentialCache.DefaultCredentials;
When the remote webservice gets invoked with these DefaultCredentials, I get the following error:
System.Web.Services System.Web.Services.Protocols.SoapException: Server was unable to process request.--->
System.Net.WebException: The request failed with HTTP status 401: Unauthorized.
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse (SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
I am not sure whether I have misunderstood and tried to over-simplify "Impersonation" or whether the remote webservice is somehow wired to only accept credentials with 3 arguments (i.e. username, password, domain).
Upvotes: 4
Views: 21461
Reputation: 1021
As @Michael Levy said, this is a double hop problem. What this means is that unless you configure Kerberos (Negotiate), NTLM is probably used in a windows environment running IIS, having a client with a browser on machine A trying to access website on machine B will have access to the site BUT, when this site will try to contact service on machine C, the pool credentials should be used instead.
The same is true for website A calling service B which in turn calls service C.
When configuring Kerberos for websites, multiple things should be accounted for. The first is to know if it is a farm or not. If it is, you must define a common user for the Pool for all machines part of the farm. This is required because Kerberos uses the domain name to identify the principal used to encrypt the security tokens.If you had different users on different machines of the same farm, since they would all be accessed through the same domain name, all requests would search for the same entry. More detailed information may be found here on Kerberos and load balancing.
For instance, say you have a site with myApp.intranet as a URL. In AD, you would have an SPN set to, say, myUser in domain MyDomain (setspn -S MyDomain\myUser HTTP/myapp.intranet). When the request is sent to the KDN (see kerberos links at the end for mor info on KDN), it will always return a token encrypted with myUser but IIS will try to decrypt it with different users. It may be tempting to create multiple SPN for a same service (HTTP/myapp.intranet) but this would make KRB error out.
Also, if you are on IIS 7+, you will have to set a little detail in your ApplicationHost.config if you want to keep Kernel-mode authentication enabled (which is strongly recommended): useAppPoolCredentials=true. This value must be set on configuration\system.webServer\security\authentication\windowsAuthentication. This is because by default, Kernel-mode auth will use the Computer account, not the pool account and this would bring us back to the multi-user scenario.
In all cases, the Trust this user for ... of the Delegation tab of the AD principal must be enabled for delegation to work. You then have to decide if you want to use general or constrained delegation.
As I said earlier, you also have to set a SPN for the right user and the right service. The user is quite easy to identify sinc it will be the one you defined on your pool but the service may get a little tricky depending on your configuration. DNS, browser and probably other variables may change what should be used. Our trials and errors have shown the following:
Note that if no SPN is specifically set and that you access your website through the NetBIOS name, the HTTP/machine service will be requested and that by default, HOST service (search for extra) may be used in place of HTTP so HOST/machine would be used. This can be useful for easy configuration on a small network.
It is also to keep in mind that if you want to limit downtime when going from NTLM to Kerberos, you should first modify the ApplicationHost, then, use SetSPN. You can also disable negotiate befor any action and keep only NTLM until everything is set up and then, if possible, enable only negotiate (without NTLM). This should force clients to modify the way they access your website. If you don't do this, caching mechanism seems to tend to keep on NTLM for a while.
Hoping this can help. If you still have problem configuring Kerberos, WireShark is your most faithful friend. You can find information on how to debug Kerberos in the following pages: - Debug Kerberos for a website - Debug AD problems with Kerberos (max token size is one of them) - Kerberos tools and other links - General network capture Kerberos debugging
Upvotes: 3
Reputation: 37803
This is classic double-hop problem - you can't use user credential gained through impersonation to access another server unless Kerberos Delegation is properly configured in your domain. Duplicate of this question
Upvotes: 1
Reputation:
@ Michael Kniskern - It is certainly possible with HTTP. The impersonate feature will pass the credentials from the ASP.Net app to IIS. With Integrated Windows Authentication, the end user's credentials will then be used instead of the default ASPNET account (or account attached to the App Pool). That MSDN article's mention to HTTP and FTP was directed at DefaultNetworkCredentials, I believe.
Upvotes: 0
Reputation: 1362
Have you used netmon or wireshark to make sure the credentials are getting passed? What's the log on the service provider telling you? Also, make sure there's no impersonation tag configured in web.config (or other .config).
EDIT:
A HostingEnvironment.Impersonate() block perhaps -- that utilizes the app pool's identity by default, or the identity of any user token you pass it.
Upvotes: 1
Reputation: 25270
According to the following MSDN article, it will not work for HTTP and FTP protcols. You will have to explicitly provide the credentials when you make a connection to the remote server.
Upvotes: 0