When sending an encrypted msmq message it seems like the authentication bogs down the speed (from 2500 msg/sec to 150 msgs/sec).
This seems to be the case for both System.Messaging.MessageQueue and the Wcf client with msmqIntegration binding.
My requirement is for encrypted transport, I can do without authentication. I would prefer the WCF client since settings can be changed from app.config.
Is there a way for the msmqIntegrationBinding to do transport encryption without authentication ?
<msmqIntegrationBinding>
<binding name="VisionAirMessagingBinding"
timeToLive="12:00:00"
maxReceivedMessageSize="4100000"
receiveErrorHandling="Move"
retryCycleDelay="00:30:00"
useMsmqTracing="false"
serializationFormat="Stream">
<security mode="Transport">
<transport msmqAuthenticationMode="WindowsDomain"
msmqEncryptionAlgorithm="RC4Stream"
msmqProtectionLevel="EncryptAndSign"
msmqSecureHashAlgorithm="Sha1"/>
</security>
</binding>
I found out that authentication slows me down by commenting out the following when using the System.
q1.Send(new Message
{
BodyStream = new MemoryStream(
Encoding.ASCII.GetBytes("ABCDEFGHIJKLMNOPQRSTUVXYZ")),
Label = i.ToString(),
//UseAuthentication = true,
UseEncryption = true
}, msmqTx);
If I switch on the authentication, sendings becomes slow again!
Thx for any help!
WindowsDomain authentication means Kerberos authentication. It is necessarily a multiple agent protocol (using something like 4+ different messages being sent). Since you are using the blocking .Send() method. This is going to limit your rate (due to multiple latency paths), if you do not throw in some asynchronicity/concurrency.
You might find that switching to simple Certificate authentication will suffice.
The result is that the server will be executing the message without the user's credentials, but will be authenticated (you know who sent the message, but you can't elevate to the that user's permissions).
Related
I need to call a web service and for easy testing purposes I’ve created a console application for that. But it needs to work in BizTalk, and it doesn't.
It’s a pretty simple configuration in the app.config file:
<basicHttpBinding>
<binding name="XXXWebService_Binding" textEncoding="utf-16">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
Before calling the web service, I need to specify the Windows credentials:
proxy.ClientCredentials.Windows.ClientCredential.Domain = "xxx";
proxy.ClientCredentials.Windows.ClientCredential.UserName = "xxx";
proxy.ClientCredentials.Windows.ClientCredential.Password = "xxx";
This works as it should work.
So I need to get this working in BizTalk. I use the WCF custom adapter with basicHttpBinding, with the same configuration as my console application:
To specify the credentials, I insert them in the Credentials tab.
When I test this, I get this error message:
System.Net.WebException: The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate'.
What could this be?
On MSDN (for the WCF-BasicHttp Adapter) I found this:
Windows: Windows integrated authentication. The user account under which this send port runs is used for services to authenticate this send port.
Could it be that the right credentials are ignored and the credentials of the host instance are used (even though I can find the right credentials in the context properties of the ‘Transmission Failure’-message)?
Windows authentication will use the account of the logged-in user for the executing process. In the case of BizTalk, that would be the Host Instance Service account.
The Credentials box is for basic authentication only. That's just how it's wired up.
I've never gone down this path, but I think you'll need to use a custom binding element, like a Behavior, to set the alternate Windows credentials.
I got this answered when I tried to use Get-OfficeWebAppsFarm:
We need to create a WCF service (.NET 4.0) that will be consumed by a client outside of our organization.
The case is that we have two servers that are behind a load balancer which terminates the SSL. This is where it gets confusing for me.
How we could and should handle the authentication?
The previous experience about WCF is only about services for internal use. If I understood correctly we should use basicHttpBinding to guarantee interoperability with Java based client. I don't know if this is an issue with JAX-WS based client.
There will only be this one client that is going to use the service.
We need to somehow ensure that caller is authenticated to use the
system
Make sure the message is encrypted when moving in public network
So far the best article that I found was
http://devproconnections.com/net-framework/wcf-and-ssl-processing-load-balancers
There were few suggestions how to do this.
WCF services can be configured for basic authentication and receive credentials in the clear over HTTP. This can work; however, it precludes passing credentials in the message, and the use of more interesting credentials (such as issued tokens).
We use forms authentication on our website under which the service will be hosted. I think it is not easy or even possible to make the service then use basic authentication.
WCF services can be configured to fake the presence of transport security so that the runtime will allow receiving message credentials without transport or message protection
Will this be the way to go and will this work with basicHttpBinding?
The client and server binding will be different. The client binding will use username auth in eitehr message or transport level with transport security (ssl):
<bindings>
<basicHttpBinding>
<binding name="NewBinding0">
<security mode="Message" />
</binding>
</basicHttpBinding>
</bindings>
then the server config will use the same config but without the transport security. If you chose to use message security then check out WCF ClearUsernameBinding. If you use trasnport security (basic http) then set mode="TransportCredentialOnly".
I'm developing a product that consists of a WCF service and several WCF clients deployed to different locations. In order to secure the service, I configured WCF to use Message Security via certificates.
In detail, these are my service configuration files:
Web.config, App.config
This is working fine as far as I can tell, even when the certificate is stored on a SmartCard (WCF even pops up a dialog asking me to enter the SmartCard's PIN in order to unlock the certificate).
But removing the SmartCard after the initial security negotiation took place does not have any effect on the connection - I can still invoke methods on the web service.
What's happening?
Does WCF message security work similar to HTTPS, where a symmetric key is established during the initial security negotiation and after that, the certificate is no longer needed?
Or could it be that I have set up the service to only use the certificate to authenticate the client, but messages aren't encrypted at all?
It is because your security configuration uses security context (default for WsHttpBinding). Security context (implementation of WS-SecureConversation) indeed works similarly to HTTPS. It uses certificate only to initial authentication and generation of security token which is used to secure following communication from the same service proxy instance. The context is established be service proxy instance and it also establish WCF session which is subject of timeout.
<security mode="Message">
<message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false" />
</security>
Try setting the establishSecurityContext to false.
I'm currently designing and developing a WCF 4 RESTful service that will be used by mobile devices. I specifically picked REST because it's supposedly lightweight and the JSON output makes parsing simple for the mobile clients.
The service takes care of the mobile devices part of the entire application. But, it requires that users log in before using the service. Basic HTTP authentication is not an option: It's insecure and a man-in-the-middle attack could easily intercept the user accounts. SSL is an option here, but I have no idea how easily SSL works on a WCF RESTful service and how simple it is to implement on mobile devices.
I've looked into Digest Authentication, but I can't really find any good information on how to implement it. And that also brings up: How am I going to allow users to add a device to their account with this? Hash the username/password combination into the Digest header along with other information?
Could someone shed some light on this? Because I'm confused as hell. There is plenty of information on the net on how to implement WCF (RESTful) services, but the moment you need to secure it, the amount of information drops significantly... Articles are welcome.
Leveraging SSL is brain dead simple in WCF and should be supported by every mobile platform at this point. You should defintiely go basic auth with SSL to keep your life as simple as possible IMHO.
All you need to do to enable HTTPS on your WCF service is:
<webHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</webHttpBinding>
That will say "only allow access to this service over a secure transport and expect a basic auth credential to be passed".
Now, the only question is, where are you hosting your WCF service? If hosting in IIS you need simply need to configure the service certificate with it and you're all set.
Another option is to do SSL up front with an F5 device or something like that. Then you have to do a little more work because, by default, WCF will not let you pass crendentials over a non-secured transport. Then you need to get into customizing your own binding and setting the AllowInsecureTransport = true on the TransportSecurityBindingElement. This will basically say "trust me, I'm doing the right thing" to WCF and allow the service to initialize propertly even though the credential will flow over a non-secure binding.
I've got a WCF service that will need to receive client credentials, and maintain some kind of role-based data, based on my auth method.
The clients will reside on many different systems, and as such, each client will have a unique userID and pw.
I'm using basicHttpBinding and have read a few articles, such as this one,
http://nirajrules.wordpress.com/2009/05/22/username-over-https-custombinding-with-wcf%E2%80%99s-channelfactory-interface/, that describe the process.
So what I'm looking for is if someone has a full client/server configured like this to take a look at so I can derive my own solution from this.
What I'd like to do is have the username and password passed in the headers for each request, passing back some kind of SecurityTokenValidationException on fail, or continuing if passing.
Thanks.
UPDATE
I'm using the wsHttpbinding with the following config on both the client and server:
<wsHttpBinding>
<binding name="wsHttpEndpointBinding" >
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
And the call out to the server from the client as follows:
ServiceReference1.ServiceClient myClient = new ServiceReference1.ServiceClient();
myClient.ClientCredentials.UserName.UserName = "billuser";
myClient.ClientCredentials.UserName.Password = "mypassword";
Response.Write("Data from WCF Service: " + myClient.GetData(1));
I think I need a bit of a hand with linking up the CustomUsernamePasswordValidator on the server as I'm still getting the '...could not be activated.' error.
Are you required to use the basicHttpBinding? That binding is really only there to provide support for legacy WS-BasicProfile implementations (i.e. ASMX). If your clients are also .NET/WCF, I would highly recommend using wsHttpBinding, which provides a plethora of security options out of the box. You could use certificates, username/password, etc. with transport and/or message security and not need to write any of the security stuff yourself. Just configure-and-go (CAG).
Security credential information is available to the service itself via the OperationContext, in case you need to access it directly from your code. If your code does need to access it, however, I would recommend writing a behavior to extract the pertinent information from the OperationContext and place it in something more application specific so that you don't have to reference System.ServiceModel everywhere you need to access information on OperationContext.