I have a SQL Database which is storing my client side certificate for WCF service and other services. (X509 etc). I would like to use this Store (instead of 'My') to retrive this certificate (instead of declaring it in web.config) and then use it for WCF.
I have tried to search on this site and google but does not seems to be much of a help.
Currently I am doing
var targetEndpoint = new EndpointAddress(targetLogicalAddress, targetIdentity);
MyTransportPortTypesClient proxy = new MyTransportPortTypesClient("WebConfigSection", targetEndpoint);
So ideally I would like to get rid of the "WebConfigSection" and instead pass some sort of WCF object which has certifictate signed.
Does anyone know how to achive this?
I have finally solved this and Here's how I did it. (I'll share my experiece so everyone can use it) This is without using any machine CertificateStore. Its purely from Database to the client Proxy.
I have created X509Certificate2 Object and assign physical file (in byte[]). You can also put password if its password protected.
Then I have assigned the certificate to my proxy client.
Something like :
proxy.ClientCredentials.ClientCertificate = __MyCertificate
Now I have manupulated my clientproxy as I was inteneted to in my app.config. and that's it. All these properties will be in your proxy object.
Hope this helps.
AFAIK it is at least very difficult, if not down right impossible. WCF uses SChannel SSPI provider for the authentication and this SSPI provider will load certificates only from the SChannel CSP provider. In order to use a certificate from the database the certificate would have to be loaded first into a PROV_RSA_SCHANNEL CSP keystore and then the certificate context of this keystore would be passed to AcquireCredentialsHandle. For instance, this is how database mirroring is able to authenticate using a certificate stored in the database. While it is possible to do all these steps in managed code too, I'm not sure if is possible to plug them into WCF: I expect it is, but probably not for the faint of heart.
Related
Using latest VS 2013 and Azure SDK 2.4, I've created a Web Role and a WCF service in it.
This service will be consumed by a standard generated .NET service reference client proxy.
I am trying to figure out what is the simplest way to secure this WCF service. I mean securing the authentication can not be hacked easy way, like clear text pwd etc.
Some additional info about the use case:
There will be only one user
It is completely OK to store any secret in client side (like username/pwd or certificate) because the client app will run in a secured place
I just would like to prevent my service to be accessed by the public. Only my secured place running client app should access it, I would like no more no less.
So I am googling the web, and more I read more I confused and overwhelmed with the options and possibilities what I do not need I think. When searching for client certificate I find overcomplicated federated auth methods with server side temp certs etc what I am not sure my simple use case requires.
Any help appreciated.
Thanks in advance
If you really want to restrict access then I would look at client certificates. Configuring azure for client certificates seems quite complex to detail in a single SO post so I'll refer you to this blog post client-certificates-in-windows-azure and I'll summarize below [I used this myself recently so I know it works]
In essence you can make your own certificates using makecert [NOTE: you may want an official SSL cert for your site and only use self-signed for your client certificates.]
You then configure your site to accept client certs - normally I'd use appcmd.exe and a startup task but as the blog post points out your site is not ready so instead you need to add this to your webrole OnStart method [I actually went down the appcmd.exe path initially and was very confused].
using (var serverManager = new ServerManager())
{
try
{
var siteName = RoleEnvironment.CurrentRoleInstance.Id + "_Web";
var config = serverManager.GetApplicationHostConfiguration();
var accessSection = config.GetSection("system.webServer/security/access", siteName);
accessSection["sslFlags"] = #"SslNegotiateCert";
serverManager.CommitChanges();
}
catch (Exception ex)
{
...
}
}
In the CertificateAuthHandler you can than validate the certificate and if you want (and I recommend) that the client certificate being sent is from your expected CA (if self-signed) or that the thumbprint of the certificate is the one you expect (if there is only going to be one) or a combination of the above.
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.
I have a tomcat application that invokes an IIS hosted ssl enabled, client auth enabled Webservice
This Tomcat application talks to multiple wenservices and probably each of them require client auth along with PKI authentication.
For the IIS Webservice the wsdl url can change hence I use
javax.xml.ws.Service(url,qname) constructor by passing the url for the wsdl ...
The thing is I need to call the above with SSL with custom client key. How to I tell the above constructor to use a sslsocket that I create with my custom KeyManager ? I do not want to use
HttpsURLConnection.setDefaultSSLSocketFactory as that will enforce other outgoing ssl connection to follow to my keymanager which is exclusive to the IIS webservice.
Thanks for your reply.
If you follow the answer to your similar question on ServerFault and make sure that Tomcat's <Connectors /> don't use the javax.net.ssl properties, setting your keystore for the default key manager might not be the end of the world. HttpsURLConnections will only authenticate with it to server that ask for it (client-certificate authentication is always requested by the server) and that ask for a client-cert from a CA list that would match your certificate's issuer. This might not be such a big problem in practice.
If you think it's too big a problem, there seems to be an undocumented property called com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory. Its documentation is as follows:
Set this property on the BindingProvider.getRequestContext() to enable
HttpsURLConnection.setSSLSocketFactory(SSLSocketFactory). The property
is set as follows:
SSLSocketFactory sslFactory = ...; Map ctxt =
((BindingProvider)proxy).getRequestContext();
ctxt.put(SSL_SOCKET_FACTORY, sslFactory);
THIS PROPERTY IS EXPERIMENTAL AND IS SUBJECT TO CHANGE WITHOUT NOTICE
IN FUTURE.
My scenario:
Many WCF clients which are in environments outside of my control
Server will either be mine OR in an environment outside of my control
So worst case the client and the server is outside of my control. More specifically, I might assume that someone hosting this code could try to maliciously impersonate either the server or the client (the server being more likely). However, the client needs to verify that the server is my code and the server needs to verify that the client is my code. I've seen all the recommendations to use certificates; however, is that an option given my scenario?
One approach I've considered is to write an IClientMessageInspector and an IDispatchMessageInspector to set and verify a custom SOAP header on both sides. I would create an HMAC signature based on a secret key contained within the source code (assume I have a way to keep this hidden) and then verify the digest based on the message body.
I feel like this would work; however, I feel like there might be something more out-of-the-box that I'm missing here. Am I close, way off track? Thanks for any guidance!
Certificates are definitely the way to go in your situation.
Your server will easily be authenticated by clients because it will provide a certificate known to each client, SSL is a good option here.
The server will also be able to authenticate clients by requesting that every client should provide a certificate (server can check for a specific issuer of the certificate - your own issuer in that case).
Now you just need to correctly manage/secure your certificate server to make sure that it won't be compromised.
I don't think there is anything out of the box to do this, simply because it is an unusual requirement for the server to verify that the code on the client calling the service is authorized code.
Generally, it is sufficient to establish trust as follows:
Server has a certificate and service uses SSL - this way clients are confident that they are connecting to the correct server machine.
Clients provide authentication details (eg username/password, certificate etc) to the server so the server knows the connecting client can be trusted.
You are attempting to go the extra step to verify that not only are the users/machines verified, but also that the code running is verified - this is simply overkill. If the code running is not verified, either:
One of the machines has been compromised, in which case you have bigger issues to worry about.
One of your users has written code against your service and is using it 'illegally'. This should not be a problem if your service only allows authorized users to perform 'dangerous' operations.
I have a WCF Server Deployed through IIS. I want to Create a Certificate for it. I could do this by making the server a certificate server.
But then when the client connects to that server I want the client to automatically trust the certificate without having to register that the server as a "trusted authority".
Is this possible?
All this seems a lot of work to put username password protection on a WCF Service!
The short answer is no the client will need to add the server cert root as a trusted authority.
The slightly longer answer is that there is a workaround for needing to implement transport security in WCF when using message based authentication - this workaround is usually used when you want to rely upon another security mechanism that the WCF server is not aware of, like an ISA server providing SSL.
Have a look at Yaron Naveh's post. The essential idea is that you create a transport binding that pretends that it is secure.
With all that, you still need security (you don't want to send your creds in the clear) and so will still need a trust chain for your cert. So, it may not actually help you, but hopefully it gives you some options to consider.
Edit
Sorry if my answer was misleading. The server certificate root cert must by in the client trusted store. My additional detail was giving another option for providing the security (you can use an ISA server with a trusted cert to give your SSL connection)
In a similar situation to yours (needing secure communication when pushing client applicaitons to non technical customers) I have programatically installed the needed root certs.
Here is an SO post that details how to do that: How can I install a certificate into the local machine store programmatically using c#?
You can if you add this to your code but be aware of what you are doing!
System.Net.ServicePointManager.ServerCertificateValidationCallback += ( se, cert, chain, sslerror ) => { return true; };
Well if there would be such a way, it would be a security hole.
If a certificate is not linked to a trusted authority it is easily forged. So your choice is either to link it one way or another (directly or through a parent certificate you control), or configure your client so that it does not require the certificate i.e. using http rather than https.
Just keep in mind that it leaves your clients open to a variety of attacks
Edit
One of the possible attack scenarios is a man in the middle attack - a program inserts itself between your service and the client and channels the information though itself. This way the intruder has complete control over the information flow.
It can make copies of passwords or it can "adjust" the results in both directions any way it wants. The only thing which prevents this from happening is the certificates. But if they are not rooted, they can be forged.