Adding a web Proxy for a client created with NetCFSvcUtil with credentials - wcf

We have an implemented a WCF service for sync framework communication with the guidance of http://wcfguidanceformobile.codeplex.com/ . The client in created by NetCFSvcUtil.
We have run into a problem when web proxy support is needed.
How can you enable credentials with it?
On the HttpTransportBindingElement we can set the proxyadress, but since our proyx requires login this won't do it.
When trying to set UseDefaultWebProxy to true it still won't use any credentials. It connects to the proxy but gets
Error 407: Proxy authentication required
Can't find any information about it on SO or msdn. Anyone got a clue where to look?

In Compact Framework, use the static GlobalProxySelect.Select property to set the global proxy used by all HttpWebRequests, including WCF service calls.
GlobalProxySelect.Select = new WebProxy(...);
For this to work in WCF, the HttpTransportBindingElement properties must be
ProxyAddress = null (default)
UseDefaultWebProxy = true (default)
The GlobalProxySelect class is deprecated in the full framework, so you should use WebRequest.DefaultWebProxy instead.

Related

How to enable NegotiateServiceCredential in WCF when using CustomBinding

I have a client that use CustomBinding to consume a web service. I'm setting the service and client certificate before sending my request, but this way I need to know the service certificate to use and have it installed in the client machine. I'd like to let the service to provide the current certificate so I don't have to update it every time it changes.
I know this can be done when using WSHttpBinding by setting NegotiateServiceCredential to True through the Security property, but since I'm using CustomBinding there is not such a property and I don't know where to set NegotiateServiceCredential to True.
Can anyone help me with this?
Thanks.
You need to create a CustomBinding that works over HTTP and has a MessageSecurityOverHttpElement element on it. There you you'll find a NegotiateServiceCredential property which will allow to enable/disable the feature.
This link should get you started writing a Custom Binding with a SecurityBindingElement. From there work your way up until you manage to add the MessageSecurityOverHttpElement.

Form Authentication on NetTcpBinding in WCF service

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.

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.

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.

How can I set an HTTP Proxy (WebProxy) on a WCF client-side Service proxy?

How can I set the HTTP proxy programmatically, on a WCF client, without using the default proxy?
Proxies, proxies, proxies.
According to the WCF model of development, I generate client-side "proxy"
classes by running svcutil.exe on the WSDL for the service. (This also
produces a client-side config file).
In my code I new-up an instance of that class and I can connect to the
service. Very nice.
var svcProxy = new MyWebService();
svcProxy.GetInformation(request);
We call this thing a proxy class, but there is another proxy - the http proxy. This
service is using wsHttpBinding basicHttpBinding, so it is going over
http. Now, suppose I want to connect the client to the web service over
a http proxy (modeled by a System.Net.WebProxy in the .NET BCL). I know
from my extensive, delightful experience reading .NET and WCF documentation, that
the WCF runtime, if not instructed otherwise, will use the default
system proxy when communicating over http/https.
I can set that from the command line in
WinXP / 2003 with ProxyCfg.exe as described here, and in later
versions of Windows with netsh.exe as described here.
I can also specify the default web proxy for use within the application
by setting the System.Net.WebRequest.DefaultWebProxy property.
But suppose I want to connect over a proxy that is different than the
system-wide proxy? For instance maybe there is no system-wide proxy but
I need to use one for the web service in particular. Or maybe there is
a system-wide proxy but I need to use a different one, for the web
service. And in fact maybe there are multiple web service clients, and
each one should get a different proxy.
How can the proxy be set per-binding?
In the ASMX model, I could do this:
var svcProxy = new MyWebService();
svcProxy.Proxy = new System.Net.WebProxy("http://proxyserver:1234", true);
svcProxy.GetInformation(request);
But this is not possible with WCF; the WCF-generated client-side proxy
classes do not expose a Proxy property. How do I set the http proxy, per client-side proxy, and how do I set authentication on the http proxy as well?
Related:
- how-to-set-proxy-with-credentials-to-generated-wcf-client
It makes sense that there is no Proxy property on the WCF proxy, because not all WCF proxies use HTTP for communication. After further review, I found that it is possible to set the proxy in WCF programmatically, if the WCF proxy uses an HTTP binding. I am documenting it here in case someone else needs it. To set the HTTP Proxy in code for a WCF client, do this:
// instantiate a proxy for the service
var svc= new ServiceClient();
// get the HTTP binding
var b = svc.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
b.ProxyAddress = new Uri("http://127.0.0.1:8888");
b.BypassProxyOnLocal = false;
b.UseDefaultWebProxy = false;
And to set the endpoint address - where to reach the server - in code, you would do something like this:
var e = svc.Endpoint;
e.Address = new System.ServiceModel.EndpointAddress(
"http://remoteserver:5555/WcfXmlElement");
The proxy settings are part of the binding configuration. For example, look at the ProxyAddress property of the BasicHTTPBinding and WSHttpBinding classes/configuration elements.
Looks like you're leaving your endpoint configuration in the app.config file, in which case you should be able to set the address there.
I have had a similar problem, but I also needed to use a username and password for the proxy that differ from the username and password used to access the service.
I tried building it up through a UriBuilder, which would output the proxy address as "http://username:password#myproxyserver/". Unfortunately, the particular proxy I was using didn't work with this technique.
What I found after extensive Googling, is that you can change the proxy through WebRequest.DefaultProxy (static property).
For example:
WebProxy proxy = new WebProxy("http://myproxyserver",true);
proxy.Credentials = new NetworkCredential("username", "password");
WebRequest.DefaultWebProxy = proxy;
You could also try this :
Programmatically get whatever binding you are using,and then set the proxy on it directly e.g.
var binding = new WSDualHttpBinding("WSDualHttpBinding_IMainService");
binding.ProxyAddress = new Uri("http://192.168.5.1:3128");
where "WSDualHttpBinding_IMainService" is the name of your binding from your config file.
Also you have to set UseDefaultWebProxy=false; otherwise your proxy will be ignored.
I found a solution for someone who might use .NET Core 2.x
Which initially cause an issue when trying to set proxy by using
System.ServiceModel.BasicHttpBinding;
as answered by Cheeso.
You have to update WCF to the latest (v.4.7.0).
Go to NuGet Package Manager -> Update all related Project URL of WCF.
There must be:
System.ServiceModel.Security
System.ServiceModel.NetTcp
System.ServiceModel.Http