I have a WCF service that has a method to return the Windows Username of a Silverlight client that is consuming the service . The WCF service is using basicHttpBinding with the TransportCredentialOnly mode set and the TransportClientCredentialType set to Windows. In IIS Windows authentication is enabled and anon authentication disabled.
Despite (apparently) configuring the service correctly when I call the service and ask it to return the username it errors. Closer examination shows that HttpContext.Current.User is always null (so a nullreferenceexception is thrown).
Does anyone have any other ideas why this is not working?
Try adding -
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
to your config file
In WCF, there is the OperationContext object from which you can retrieve the security credentials passed in by the caller/client by using the ServiceSecurityContext property.
Related
I've seen a lot of posts about the WCF double-hop issue with impersonation, but none of them have specifically helped me resolve my problem.
What am I missing? What else do I need to do in order to retain my Impersonated User (DOMAIN\UserName) over on Service 2? I'm looking at ServiceSecurityContext.Current.WindowsIdentity.Name to confirm - maybe that's wrong.
The Setup:
Client App hosted in localhost IIS with Service Reference to Service 1 - Impersonating WindowsIdentity (DOMAIN\UserName)
Service 1 - WCF Service hosted in localhost IIS with Service Reference to Service 2
Service 2 - WCF Service hosted in localhost IIS
I'm using ALL basicHttpBindings to keep things simple. I've set up SPNs on both service endpoints.
I can successfully MAKE the double-hop and the code executes just fine
In Service 1 (hop 1) my ServiceSecurityContext.Current.WindowsIdentity is the person that I impersonated (DOMAIN\UserName)
In Service 2 (hop 2), my ServiceSecurityContext.Current.WindowsIdentity is the IIS App Pool user
ImpersonationLevel = "Delegation"
Both WCF Services have Windows Authentication Enabled and Anonymous Disabled
** Note: I'm running this all locally on my dev box. Even so, I've had my delegation level set to allow delegation from myself to myself. Maybe overkill.
Binding (similar for both services):
<binding name="...">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
I've set the impersonationLevel = "Delegation" on both the WCF service client and the service endpoint behavior configuration. My service methods are specifically decorated with impersonationOption="Allowed" (hop 1) and impersonationOption"Required" (hop 2).
As it turns out, the critical piece in my case was ensuring the following behavior attribute was set:
<serviceAuthorization impersonateCallerForAllOperations="true" />
Previously, when I set this value, I was receiving errors in Entity Framework, so I undid the setting. It appears that somewhere along the line of aligning my setup to the standard implementation (as described in other varios posts) that I was able to eventually set this attribute and have it work as expected.
Edit:
If this all works locally, but doesn't work in a distributed environment, check out this post: How can I fix the Kerberos double-hop issue?. You probably need to set the machines to trust delegation between each other.
I am using WCF service, which have two endpoint WsHttpBinding and NetTcpBinding and the service is using Forms Authentication. Service is hosted on IIS 7.
This works perfectly with WsHttpBinding, but fails for NetTcpBinding.
It fails on below statement:
FormsAuthentication.SetAuthCookie("COOKIENAME", false);
And the exception is :
Object reference not set to an instance of an object.
Please share your ideas on this.
Forms Authentication requires cookies/session which is not supported by protocol itself.
So, Forms authentication can not implemented on NetTcpBinding of WCF service.
Option 1:
As an Alternative:
Add references to System.IdentityModel & System.IdentityModel.Selectors as well as the WCF assemblies.
Set the security mode to Message on your binding
Set the Message.ClientCredentialType to MessageCredentialType.UserName
Create a type derived from UserNamePasswordValidator and implement the only method. You should throw a SecurityTokenException if the user name / password pair does not validate.
On your service host instance's Credentials property, set:
UserNameAuthentication.UserNamePasswordValidationMode to UserNamePasswordValidationMode.Custom
UserNameAuthentication.CustomUserNamePasswordValidator to a new instance of your UserNamePasswordValidator-derived class.
Set a service certificate with ServiceCertificate.SetCertificate()
As for the client-side credentials dialog, you can either make one yourself and on your proxy set proxy.ClientCredentials.UserName.UserName & proxy.ClientCredentials.UserName.Password before you open the proxy / use it the first time. Or you can check out how you can implement the System.ServiceModel.Dispatcher.IInteractiveChannelInitializer to create your own interactive initialization UI.
Option 2:
Another Alternative this sounds more like what you want to do ..Passing FormsAuthentication cookie to a WCF service
Why did I provide an answer to an old post - because someone might be looking for an answer. Hope this helps.
In a related post, I am having trouble connecting to a basicHttp endpoint and it seems that it is due to WCF impersonation issues when connecting to a downstream service. The funny thing is that it works fine when I replace the basicHttp WCF service with an ASMX web service. Both services use <identity impersonate="true" userName=".." password=".." /> from ASP.NET web.config file, but the ASMX service works while the basicHttp WCF service doesn't.
Does this seem likely to be some sort if Kerberos delegation issue between ASP.NET and WCF?
Or is there something that I can add to my WCF configuration to pass this impersonated user (note I am using framework 4, so I currently have almost no configurtation)?
Finally worked out that I needed to add <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> to the WCF part of the web.config file, and an AspNetCompatibilityRequirementsMode attribute to the implementation of the basicHttp endpoint. This will then call the downstream netTcp endpoint using the credentials defined in <identity impersonate="true" userName=".." password=".." />.
Trying to create an framework 4.0 WCF basicHttp service hosted by IIS (6) that is completely unauthenticated. Once deployed, I can successfully retrive the WSDL via a browser.
However whenever I try and connect to it via WCF Test Client or via a visual studio generated proxy, I'm getting "The server has rejected the client credentials.".
This still occurs when I add <security mode="None"/>, but my understanding is that this is the default anyway ...
In the IIS virtual directory properties I only have anonymous ticked, and in the web.config file <authentication mode="None"/> is set as well.
Any ideas?
Seems like the IIS site has anonymous authentication disabled. Check out this article on IIS 6 anonymous access configuration.
Turns out that the source of the exception was from an immediate attempt to connect to a downstream tcp service. As a workaround I ended up creating a plain jane webservice wrapper which successfully connects to the downstream service fine using a domain account specified in the <identity impersonate="true" userName=".." password=".." />.
Note, I've added a related question asking why one works and the other doesn't.
I have some WCF services that are hosted by IIS with ASP.Net compatibility turned on.
I have the following in my web.config:
< serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
And my service class is decorated with the following:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
For some weird reason, the HttpContext.Current is null for the first request after the web app starts up. The HttpContext.Current is not null for following requests as expected.
Does anyone have an idea why it isn't working for the very first request?
The call to HttpContext.Current is from within a custom UserNamePasswordValidator class I wrote to check creds stored in the database.
Turns out this is a bug in the framework that was fixed in 4.0. more info
If you are using IIS 7.0 integrated mode to host your application HttpContext.Current might not be initialized in Application_Start so if you are trying to access it there it will crash.