I just don’t seem to get my head around this. I need to enable via code or config, a way where in the client can authenticate the service and also service can authenticate the client.
What does
<Identity> play a role in this?
Can i specify the client credential here?
And what needs to be filled here
<serviceCertificate>
</serviceCertificate>
<windowsAuthentication>
</windowsAuthentication>
I need to understand the way the certificate are exchanged and various ways of doing so.
Related
MSDN for <serviceCertificate>says this
This configuration element specifies the settings used by
the client
to validate the certificate presented by the service using SSL
authentication.
MSDN for <identity> says this
In the handshake process between the client and service, the Windows
Communication Foundation (WCF) infrastructure will ensure that the
identity of the expected service matches the values of this element,
and thus can be authenticated.
As I understand, both these elements are used to authenticate service to the client.
Question: Could someone please elaborate and let me know the difference?
Thanks!
These are quite different.
As its name implies, the <identity> element is used by the client to identify a service, answering the question "Who are you?" It contains many child elements that can be used for this purpose - as there are many ways of identifying a service: certificate, SPN, UPN, etc.
<serviceCertificate> specifies an actual X.509 certificate used to authenticate a client or service, helping to answer the question "How can I be sure you are who you say you are?"
I have a server with SSL certificate and would like to implement a WCF service with username authentication. Can anyone point me to a simple current example?
I find lots that use the 509 certificate and I don't understand why that additional piece would be needed. I don't think I want to give the certificate I have for the SSL to the client either.
I think to use SSL is just setting up the web.config appropriately with wshttpbinding and using https: in the uri that calls the service.
In this case I will have only one or two users (applications at the client actually) that need to use the service so I don't see the overhead for building a database for the store for lots of login credentials or anything like that. I've read you can pass the credentials in the request header. I hope I can just have the service itself check them without tons of overhead.
I'm really struggling to get how a simple authenticate can work for a service but I know I need something in addition to the service being SSL encrypted.
Edit: Hummm having read more I get the impression that using https binding for the message circumvents any notion of username credentials without something mysterious with certificates going on. I hope I haven't wasted money on the ssl certificate for the server at this point.
Can the IP of the requestor be used to allow the service for a known client only?
If you only need a couple of users, then use the inbuilt Windows authentication - create Windows user accounts, put the right security option in your binding config and you're done. If you're using SOAP from a non-windows client you'll have to perform some tricks to make it communicate properly (typically we found using NTLM authentication from PHP client required the use of curl rather than the PHP SOAP client library, but I understand that if you use AD accounts this becomes much easier).
WCF docs have a full description of auth options for you.
So I've done some research and found out that, indeed, WCF prevents us from sending username/password in clear text. The basic argument is that "it is not secure, because it allows a hacker to intercept credentials". Hence, a secure channel is required, and for that, the server needs an X.509 certificate.
Ok, point taken. But here's a problem: said certificate needs to be trusted on the client. But why?
A trusted certificate is commonly used on Internet-open servers to enable clients to verify the server's identity (i.e. make sure they're not connecting to a bogus server). But what if server's identity is not important in a given context?
My product consists of two applications. Let's call them client and server1.
The basic scenario is this:
The user connects to a network that has one or more of those servers installed and opens the client application
The client uses WCF discovery to find any servers on the network
(or, optionally, the user can specify server's address manually)
The user chooses which server he wants to connect to, and then enters username/password for that server
The connection is established, the client does some calls to the server on behalf of the user
One can see how in this scenario, the user doesn't need to verify that the server is not bogus. Even if he wanted to, there is nothing to verify against. After all, the only thing we know about the server is that it supports our protocol, and that fact doesn't need verification.
In other words, I need communication confidentiality and client authentication, but not server authentication.
It would be bad enough to ask my customers to purchase a certificate from a trusted authority for every server, but it would be even worse not being able to explain why exactly they need it.
Given all the above mentioned points, I see three possibilities:
The WCF designers simply didn't think about this scenario. That is, WCF doesn't support it.
(at least natively; yes, I am aware of Yaron Naveh's creation).
I am missing some detail that implies that the certificate does have to be trusted after all.
There is a way (unknown to me) to use certificate just for encryption and not for server's authentication, and thus avoid making it a trusted one.
So the question is:
Which of these three options is the case? And if it's the third one, what is that way? (My fingers are crossed for number 3 :-)
.
.
1 It is important to note that the term "server" is not used in the "Internet" sense here. That is, the server is not a computer on the web, but rather a program that gets installed on some computer, not necessarily even connected to the Internet. And there going to be many of these, installed by different customers on their sites, most times without my direct knowledge.
To avoid certificate validation, add following in system.serviceModel/behaviors/endpointBehaviors/behavior/clientCredentials/serviceCertificate element:
<authentication certificateValidationMode="None" />
Each "server" doesn't have to have it's own unique identity. All "server" instances could use the same identity and you just configure the client to expect that identity no matter which "server" it's talking to. That way the client doesn't care as long as all "servers" use the same identity. Essentially this boils down to buying/generating a single certificate for the "server" identity and just making sure that all your "server" instances use this identity in their communication.
From a "server" configuration perspective you just make sure that keypair is installed and use the <serviceCertificate> configuration element to use it:
<behavior name="MyServiceBehavior">
<!-- ... -->
<serviceCertificate findValue="AcmeCorpServer" storeLocation="LocalMachine" storeName="My" X509FindType="FindBySubjectName" />
<!-- ... -->
</behavior>
And then on clients you just make sure you have the public key installed and configure the endpoint behavior:
<behavior name="MyEndpointBehavior">
<!-- ... -->
<clientCredentials>
<clientCertificate findValue="MyClient" storeLocation="CurrentUser" storeName="My" X509FindType="FindBySubjectName" />
<serviceCertificate>
<defaultCertificate findValue="AcmeCorpServer" storeLocation="CurrentUser" storeName="TrustedPeople" X509FindType="FindBySubjectName" />
</serviceCertificate>
</clientCredentials>
<!-- ... -->
</behavior>
This is more of a coarse grained approach to security, but it seems like it would fit your particular needs. It's basically like saying "allow my client to talk to any service that might ever exist as long as we can validate the identity to be our identity".
Finally, if you can't/don't want to do this with configuration for some reason (i.e. you can't/don't want to put things into certificate stores) there's ways to do it programatically as well by loading the X.509 certificate manually and then assigning it to the client/server behavior at runtime.
I want to secure my WCF service.
For example if I want to generate public / private key pair without involving any third-party certification authority.
What is the way and method to do it?
Any idea or any other approach.
You can create test certificates using "makecert" commands as shown here. You can bypass certificate validation checks using configuration such as below, although this is not recommended in a production environment:
<authentication certificateValidationMode="None"
revocationMode="NoCheck" />
I'd have a good read of the configuration options for different scenarios at this CodePlex link, it will show you the different security options and how to configure them.
I am encountering the following problems trying to work through the quagmire of settings in WCF...
I created a WCF client-server service using a NetTcp binding. I didn't make any changes to the security settings and when running on one machine it works very nicely. However, when I ran my client from another machine it complained that the server didn't like the security credentials that were sent.
I understand now that NetTCP is "secured" by default and that my client would have been passing the wrong security details - namely the Windows user name and password (or some form of domain authentication) to my server which as they are not running on the same domain it would not have liked.
However, what I don't understand is as follows:
I haven't specified any security in my binding - does the standard settings expect a Windows user name or password to be sent?
I don't have any certificate installed on my server - I understand that NetTCP bindings need some form of public private key to protect the credentials - yet this seemed to work when both client and server were on the same machine - how was the data getting encrypted? Or wants it as WCF knew it was on the same machine and encryption isn't needed?
I have had to set my security mode on my client and server to "none" now and they connect nicely. However is there a way to encrypt my data without a certificate?
Finally... what is the difference between Transport and Message security?
To check my understanding (excuse the scenario!) message security is like if I sent a letter from person A to person B and I encode my hand writing to ensure that if anyone intercepts it they cannot read it? Transport Security is if I decide to have my letter sent by armed transport so that no one can get at it along the way?
Is it possible to have any form of encryption in WCF without a certificate? My project is a private project and I don't want to purchase a certificate and the data isn't that sensitive anyway so it's just for my own knowledge.
The default client credential type for NetTcpBinding is Windows Authentication. For Windows Authentication to work both client and server must be in the same domain, or mutually trusting domains (which in your case you do not have).
If both client and server were on the same domain, WCF would handle the mechanics of Windows Authentication "behind the scenes". And when both client and server are on the same machine they are effectively within the same domain, so Windows can use its own mechanisms to handle the encryption and decryption. It will only do this within mutually trusting domains, though.
If you don't have mutually trusting client and server domains, then the client and server must have some other way to determine if they trust each other with their keys. That's where certificates come in. The client and the server have their own certificates (or the server can issue the client a certificate).
Transport security is like encrypting the outside of the envelope as well as the inside. The downside is if you have to pass the envelope to someone outside your own organization, they need a decryption key just to know where the envelope is supposed to go--now they can read the message in the envelope also. On the other hand, transport security is faster--it requires less security overhead data getting passed along with your envelope.
Message security encrypts your message, but the envelope can be read by the postal workers (the internet and its routers). Only the source and the destination have the keys to decrypt the message, but the intermediaries can properly route your message.
To summarize: to use encryption over the NetTcpBinding both client and server must be within a domain (or mutually trusting domains) or you must have a key exchanging certificate.
Edit: I was asked for some example code--here is a binding element in XAML. It would normally be placed within a netTcpBinding element.
<binding name="Secure" listenBacklog="4000" receiveTimeout="00:20:00" sendTimeout="00:20:01"
maxReceivedMessageSize="2147483647" maxConnections="200" portSharingEnabled="true">
<!-- ~2 GB -->
<readerQuotas maxStringContentLength="2147483647"/>
<!-- ~2 GB max string content length -->
<security mode="Message">
<transport clientCredentialType="None" protectionLevel="EncryptAndSign"/>
<message clientCredentialType="None"/>
</security>
</binding>
The important part is the security element. For transport security one would change the mode attribute to "Transport". More than likely the clientCredentialType would not be "None" but rather "Certificate", "Ntlm", or "Windows" depending on the context.