Form Authentication on NetTcpBinding in WCF service - wcf

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.

Related

Nothing happens after adding service to Wcf Test Client

I added the service to the WCF Test Client app and I get Service Added Successfully, but I don't see any of the operations available.
This WCF service is already being consumed by several javascript charts, so I should be able to see something here.
What am I doing wrong?
By default, WCFTestclient doesn’t support call the Restful service by using a client proxy. WCF creates the Restful style service with WebHttpbinding. thereby the client proxy class generates nothing thought the service WSDL is available.
Besides, we are capable of making a successful call to the service by using a client proxy. please refer to the below link.
WCF: There was no endpoint listening at, that could accept the message
the above client proxy class is generated by adding service reference.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
Here is a detailed exposition of WCFTestClient from Microsoft document.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/wcf-test-client-wcftestclient-exe?redirectedfrom=MSDN
Feel free to let me know if there is anything I can help with.
 

Restricting WCF TCP endpoint to Administrators

How do I restrict access of a remotely-accessible WCF endpoint to a local/domain administrator?
Edit: After adding [PrincipalPermission(SecurityAction.Demand, Name = "AdminUser")] to my WCF channel method implementation, trying to call the service method from my client throws a SecurityAccessDeniedException, which is progress.
How do I let Windows prompt the user for new user details (or a security token) so I can reinitiate the WCF connection as the correct user?
You can do this with the PrincipalPermissionAttribute added to the methods declared in your WCF service.
See this link: How to: Restrict Access with the PrincipalPermissionAttribute Class

How to write code that calls a WCF service and falls back from Kerberos to NTLM if needed?

I need to call a WCF service programmatically. The service may be hosted with either NTLM or Kerberos authentication and needs to work under either. That is, if connecting to the service via Kerberos fails, then it should fall back to NTLM.
Here's the code I'm using for Kerberos auth (if relevant, the service is hosted in SharePoint 2010 and is being called from a web part):
public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
var binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
url = url.EndsWith("/") ? url + SiteMembershipAddress : url + "/" + SiteMembershipAddress;
var endpoint = new EndpointAddress(url);
var proxy = new SiteMembershipSvc.SiteMembershipServiceClient(binding, endpoint);
proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
return proxy;
}
Calling a method on the proxy when run in an NTLM environment gives the error:
The HTTP request is unauthorized with
client authentication scheme
'Negotiate'. The authentication header
received from the server was 'NTLM'.
Note: The URL may be in another web application on another server. I can't check what authentication the web part's web app runs under and assume it is the same as where the WCF service is hosted.
How can I (automatically or manually) ensure authentication falls back from Kerberos back to NTLM on failure?
Update:
As mentioned, the authentication error occurs when a web method is called. However I don't want to wait that long as there are several web methods in the service called from several places. I'd like to test the authentication at the point where the proxy is configured (in the code snippet above).
I've tried using proxy.Open() but that doesn't seem to cause the failure.
This is a bit off a curveball, but why is it falling back to NTLM. I've had significant difficulty with security in active directory and WCF all related to service principal names (SPNs).
Kerberos will fail if you are running the service as something other than Network Service unless you have an SPN declared in the domain for your service. To set the SPN you need the windows server administrative kit, which has the command setspn.
setspn -A HTTP\machinename domain\service_account
This will then allow Kerberos to share client credentials to your service within the domain.
Please do some reading, as you could break kerberos for any other services running on the same box depending on your setup.
(I recognize the original post is very old.)
Can you use something other than BasicHttpBinding (like WsHttpBinding)? According to this article, BasicHttpBinding is the one exception to the binding objects, in that it does not automatically negotiate. This is why allowNTLM has no effect.
I had the same error msg which I posted about here and solved it by creating a dynamic endpoint like so:
public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
//create endpoint
EndpointAddress ep = new EndpointAddress(new Uri(string), EndpointIdentity.CreateUpnIdentity("MyDomain\WCFRunAsUser"));
//create proxy with new endpoint
SiteMembershipSvc.SiteMembershipServiceClient service = new SiteMembershipSvc.SiteMembershipServiceClient("wsHttp", ep);
//allow client to impersonate user
service.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
//return our shiny new service
return service;
}
I was running the WCF service as a specific Active Directory user rather than the default NETWORK_SERVICE.
Try setting:
proxy.ClientCredentials.Windows.AllowNTLM = true;
According to this, AllowNTLM is now obsolete - i'm not sure what the correct alternative is.
I guess you are using the full dns name of the server as the address of the service. Try using the NETBIOS name or the IP address. That should force it to use NTLM.
If you know what protocol the server is using you can configure your app to use either the full name or the ip.
Hope that works for you.
If your Kerberos fail it will automatically default to NTLM, you don't have to do anything special.
http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part1.html
http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part2.html
http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part3.html
I haven't been able to find a way to do this automatically. Instead I've added UI to the application where the type of authentication must be chosen.

WCF Authentication using basicHttpBinding and custom UserNamePasswordValidator

My first question is, is it even possible to use a custom UserNamePasswordValidor with basicHttpBinding?
I have a asp.net web site using Forms authentication and a custom membership provider. I realise that I could use the built in System.Web.ApplicationServices.AuthenticationService to authenticate my client (a WPF app) but I don't want two service calls (one for auth service, one for logic).
So it seems that a custom UserNamePasswordValidator would be perfect for the job. In my client I can then have:
var service = new MyServiceClient();
service.ClientCredentials.UserName.UserName = "username";
service.ClientCredentials.UserName.Password = "password";
MessageBox.Show(service.SayHello());
I've seen this working with wsHttpBinding but ideally would like to test without an SSL certificate.
Alternatively, is it possible to make use of the AuthenticationService from within another WCF service?
To clarify what I mean above regarding authentication service, I don't want to have 2 service calls i.e:
if (authService.Login("username", "password"))
// then call my service
I know this a minor thing but the external developer of the client app is expecting just one service that takes the credentials and returns the required data.
Thanks,
Ben
check ClearUserName binding: http://webservices20.blogspot.com/2008/11/introducing-wcf-clearusernamebinding.html It should solve your problem.
I use UserNamePasswordValidator over basicHttpBinding on a couple of my current projects. It works great; however, like Brett Robi mentioned in the comments, you need to have your Security mode set to Message or TransportWithMessageCredentials in order for the validator to be called. These security modes require SSL through.
So in short - Yes you can over basicHttpBinding; however, only with SSL. Removing the security mode and SSL removes the credential validations from being called.

Identity of thread in self hosted WCF service when called from Web Application

I have a Windows Service that is self hosting a Wcf service, this Wcf service has a tcpBinding with default settings. The Windows service is running as LocalSystem.
The Wcf Service is referenced (default settings) by a Web application that is running in IIS 7.5 integrated pipeline within it's own application pool with its own identity.
Both are running on the same machine.
All is working fine, except that when in the Wcf Service when I check the identity of the current thread with:
Thread.CurrentPrincipal.Identity.Name
It returns the user of the Application Pool of the Web Application.. this is not what I expect. It looks like some sort of impersonation is going on in the Wcf service.
Is this standard behavior? I can't find any documentation on this.
And does it mean that when I try to access a database in the Wcf service i'm introducing a identity hop?
Edit, the config on service side:
Type serviceType = typeof(WcfService);
host = new ServiceHost(serviceType);
Binding tcpBinding = new NetTcpBinding( );
Uri tcpBaseAddress = new Uri("net.tcp://localhost:8001/Test");
host.AddServiceEndpoint(typeof (WcfService), tcpBinding, tcpBaseAddress);
host.Open();
On the client side:
NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.Transport);
windowsService = new WindowsService.WcfServiceClient(tcpBinding, new EndpointAddress("net.tcp://localhost:8001/Test"));
I'm reading from Learning WCF by Michele Bustamante. I have used WCF for an application that I've refactored and we're interested in using WCF in new applications for the flexibility it offers. One of the downsides of WCF is that it can be tricky to use the .net attributes or .config files to get the settings just right. I have spent days tracking down issues with the WCF settings. I've even created automated tests that will check that my service runs the way it's supposed to.
In response to your question, Michele says very specifically in Chapter Seven that NetTcpBinding is secure by default, meaning that callers must provide Windows credentials for authentication. I believe that would explain why the thread appears to be running as the identity of the web service. This is to protect your service from being called by an unauthorized user.
I believe that the following quotation from pp. 419-420 will answer your question concisely. "If you are familiar with traditional .NET role-based security, you know that there is a security principal attached to each executing thread. That security principal holds the caller's identity, which may be tied to a Windows account or a custom database credential, and its roles."
That seems to state plainly that yes, this is standard behavior.
I believe that you can change the behavior through attributes and .config files. I recommend you get a good book on the subject. I spun my wheels in the sand a long time trying to get bits and pieces of information about WCF from the web.
To clearify:
I was checking the wrong property here. Because code would be executed under the WindowsIdentity.GetCurrent() identity.
By default this is NOT the same as the caller (which is in Thread.CurrentPrincipal.Identity). If you want this behaviour you can control this with:
host.Authorization.ImpersonateCallerForAllOperations = true;
and
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
We actually have integrated security set at the website, and then any calls from the website to the WCF service we wrap in:
using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
{
That makes sure the credentials of the logged in user are passed through, rather than the IIS app pool credentials.
Works like magic!
More information is needed, but I'm guessing that it's somewhere in the configuration for the binding on either the server side or the client side that impersonation is enabled. When adding service references, svcutil.exe is VERY aggressive in setting EVERY possible binding property in configuration.
If you could provide more information for the configuration on the server and client side, it would be appreciated.