Add Header to WCF RequestSecurityToken Message - c#

I'm attempting to set up a client (Web Application) and service (WCF Service) that will communicate using a WSHttpBinding. It appears that in order to use this binding the client sends preliminary messages to set up the channel.
Between the client and the service exists a service bus which is routing on a custom header. The message, when using BasicHttpBinding security, routes without issue.
My question is: Is there any way to add the same custom header to the preliminary RequestSecurityToken message?
Thank you in advance.

This has been resolved.
Unfortunately, according to the MSDN documentation, a service using WCF transport security cannot go through a router, nor should either, service nor client, be located on the internet (https://msdn.microsoft.com/en-us/library/ff648863.aspx#TransportSecurity).
We wanted to violate both 'principles'.
So in order to cut down the messages, from five calls and responses to one, we switched to Message Security and turned off EstablishSecurityContext and NegotiateServiceCredential. - This had to be done on both the Service and Client configuration settings.
In addition to this, a noteworthy tip may be that, in order to point the service to our service bus, we changed theClientViaBehavior of the service on the Client Side.
Turn off EstablishContext and NegotiateServiceCredential:
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = false;
Point client to Service Bus:
serviceClient.Endpoint.EndpointBehaviors.Add(new ClientViaBehavior(new Uri("http://url/WCFService/ServiceName.svc")));

Related

Set ServiceBehavior on channelfactory WCF Net.Pipe

I am hosting a Net.Pipe WCF service from a forms application, which runs on a server for mostly internal calculations. To improve on this I was tasked with creating a Rest shell around this service so it becomes reachable from outside of the server. I managed to connect to this service with ease, but as soon as I drop it on the live server My rest shell can no longer connect, I tried debugging this, but the main error message that gets logged is:
The server was unable to process the request due to an internal
error. For more information about the error, either turn on
IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute
or from the serviceDebug configuration behavior) on the server in
order to send the exception information back to the client, or turn on
tracing as per the Microsoft .NET Framework SDK documentation and
inspect the server trace logs.
Thing is that I connect to this service from code and I cannot figure out how to either convert the way I connect to a service host so I can add the Service behavior or add the behavior to my channel factory.
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
ServiceDebugBehavior behavior = new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true };
EndpointAddress ep = new EndpointAddress("net.pipe://localhost/IPCService");
ChannelFactoryfactory = new ChannelFactory<RadanWrapper.IRadanContract>(binding);
// This line doesn't work
factory.Endpoint.EndpointBehaviors.Add(behavior as IServiceBehavior);
_channel = factory.CreateChannel(ep);
So the question is either: How do I connect the behavior to the channel factory, or alternatively, how can I connect to this net.pipe service through service host. (I am still looking into the second options)
I found the problem, I tried adding the behavior to the rest shell (connecting end), while it should have been added to the forms application (Hosting end) that was hosting the net.Pipe WCF
ServiceHost serviceHost = new ServiceHost(typeof(IPCService));
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
// Create new behavior, remove any existing behaviors and add this new one.
var behavior = new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true };
serviceHost.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
serviceHost.Description.Behaviors.Add(behavior);
serviceHost.AddServiceEndpoint(typeof(IPCService), binding, "net.pipe://localhost/IPCService");
serviceHost.Open();
Good thing I now got an actually working error message, turns out I was missing a specific dll that didn't get build correctly during deployment to the server.

How to make client automatically detect if WCF service is down or lost connection

I've looked at a bunch of threads like Detect if wcf service is activated but these solutions require the client to proactively detect if the WCF service is running. But what if I am in the middle of a transaction and the WCF service goes down or the connection is lost for some reason? In my testing there is no exception thrown; either nothing happens at all or that twirly circle thing just keeps going round and round. I want the client to detect if the service/connection is lost and gracefully tell the user it's down. I have timeouts set in my code:
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
binding.OpenTimeout = TimeSpan.FromSeconds(15);
binding.SendTimeout = TimeSpan.FromSeconds(3000);
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
this._engineChannel = new DuplexChannelFactory<IEngineApi>(this, binding, new EndpointAddress("net.pipe://localhost/Engine"));
But if I am in the middle of a transaction nothing actually happens; these timeouts don't seem to affect anything.
You can use one of the two approaches:
1
The two things I do are a telnet check to make sure the WCF process
has the socket open.
telnet host 8080 The second thing I do is always add an IsAlive method
to my WCF contract so that there is a simple method to call to check
that the service host is operating correctly.
public bool IsAlive() {
return true; }
Source: Pinging WCF Services
2
Use the Discovery/Announcement feature introduced in WCF 4.0
Discovery depends on the User Datagram Protocol (UDP). UDP is a connectionless protocol, and there is no direct connection required between the client and server. The client usages UDP to broadcast finding requests for any endpoint supporting a specified contract type. The discovery endpoints that support this contract will receive the request. The implementation of the discovery endpoint responds back to the client with the address of the service endpoints. Once the client determines the services, it invokes the service to set up call.
Simple usage example: http://www.codeproject.com/Articles/469549/WCF-Discovery

WCF service message security

I have a problem with message security in WCF. I'm using this tutorial: http://www.codeproject.com/Articles/96028/WCF-Service-with-custom-username-password-authenti
I have 2 services. First one, with wshttpbindig is OK. Second one, with wsdualhttpbinding doesn't work. I have an exception when I'm opening proxy after setting Credentials. It looks like I have to set Credentials before I open proxy, but I can't open proxy after set Credentials. I was using only one certificate for both services.
What I should do with this?
When I have 2 services do I have to use 2 certificates? If yes how can I do it?
InstanceContext context = new InstanceContext(this);
proxy = new CommunicationServiceReference.CommunicationServiceClient(context);
_proxy.ClientCredentials.UserName.UserName = UserSession.Login;
_proxy.ClientCredentials.UserName.Password = UserSession.Password;
_proxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
_proxy.Endpoint.Address.Uri.Port.ToString();
_proxy.Open();
EDIT:
Is it possible to configure service with wsdualhttpbinding using tutorial i posted above?

WCF Binding with SOAP HTTPS and Duplex

I've found myself in need of finding a WCF Binding that uses HTTPS/SOAP and must be duplex. I was programmatically using NetTcpBinding before but the binding now has to be HTTPS/SOAP. I did some research and it seems like it's not possible without creating your own CustomBinding.
However I'm sort of at a lost in what to do (not very familiar with bindings and the setup). I can't seem to get correct binding elements for what I need:
public class CustomHttpsBinding : CustomBinding
{
public CustomHttpsBinding()
{
}
public override BindingElementCollection CreateBindingElements()
{
ReliableSessionBindingElement https = new ReliableSessionBindingElement();
SecurityBindingElement security = SecurityBindingElement.CreateCertificateOverTransportBindingElement();
CompositeDuplexBindingElement duplex = new CompositeDuplexBindingElement();
SslStreamSecurityBindingElement ssl = new SslStreamSecurityBindingElement();
MessageEncodingBindingElement encoding = new GZipMessageEncodingBindingElement((MessageEncodingBindingElement) new BinaryMessageEncodingBindingElement());
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
return new BindingElementCollection(new BindingElement[] { https, security, duplex, ssl, encoding, transport });
}
It gives me an invalid operation exception when checking soap over secure transport requirements saying my contract is configured with an authentication mode that requires integrity and confidentiality. However the transport cannot provide integrity and confidentiality.
Seems like my HttpsTransportBindingElement is not correct? I'm not sure.
Thanks
edit:
I did manage to get WSDualHttpBinding to work at one point, but it seems like HTTPS is not possible with it (as well as others on the internet which say it shouldn't even be used)
HTTP isn't duplex protocol - its request / response - that's why wsDualHttpBinding uses two connections - one in each direction. Silverlight achieves duplex over HTTP by polling for messages from the client under the covers
NetTcpBinding uses TCP which can quite happily be duplex
If you can wait until 4.5 is released later this year this has the NetHttpBinding which does duplex using the WebSocket protocol

Consuming a wcf service over the internet

I have a wcf service that uses the WsHttpBinding as a binding.
This service is hosted on a server that has a public IP.
I need to consume this wcf service over the internet, but it is giving me the below error.
here was no endpoint listening at http://IP:9962/MyService that could accept the message.
Any Help is very appreciated.
It's a non-standard HTTP port, so my first question would be - firewall / routing issues?
I found the answer.
1- I need to add security on the binding that i am using.
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
2- I need to add custom authentication on the service host.
svh.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
People365UserNameValidator cs = new People365UserNameValidator();
svh.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = cs;
svh.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine,
StoreName.TrustedPeople, X509FindType.FindByIssuerName, "Certificate Name");
3- i need to add a certificate in the mmc of the computer

Categories

Resources