How to make sure Client Certificate is passed to Server - wcf

I have an application that needs to communicate with a third-party SOAP/WCF API using a client certificate. I have tried everything on the web how to call SOAP/WCF API using a client certificate. But every time I am getting a client certificate authentication failed. Is there is a way to see whether I am passing the client certificate or not? Fiddler is not showing whether the client cert is sent with the request or not.

Related

How do I attach the client certificate to a SOAP request?

I have a VB.NET website configured in IIS to use client certificate authentication.
When a user opens website url, he gets a popup to choose the certificate. Once the user is on the web page there is a button, clicking this will make a SOAP request to a 3rd party.
Presently I am able to use a single certificate stored on the server to make the SOAP request (by attaching the certificate). Thus the same certificate is used irrespective of which user clicks on the button.
How do I attach the client certificate of the respective user to a SOAP request? Is this possible?
How do I attach the client certificate of the respective user to a SOAP request? Is this possible?
simply attaching the public certificate of client makes little sense. If you need to co-sign the SOAP request with client certificate, then you need to send unsigned SOAP request to client (say, client downloads the request from your web site), sign it, send to server, allow the server to co-sign the SOAP request and then submit this SOAP request to 3rd party.
You cannot upload client certificate to server in order to make SOAP signing on server. It is unsupported and vulnerable approach. Client certificate's private key (which is used to sign data) MUST NEVER leave client machine/device. If you need to sign anything with client certificate, signing operation must be performed on that client only.

Restrict endpoint to specific caller

I'm working with an old legacy app at work that's written in ASP.NET 4. We recently started migrating to the cloud and we had to expose one of the endpoints so that our api gateway (Apigee) can call it. What is the correct way to restrict this endpoint so that it only allows calls from Apigee? I'm aware 2-way-ssl should solve this issue but that requires changes on the Apigee side and we don't have control over that. Is there something I can do on the API side to confirm that the certificate in the request is specifically from Apigee?
You're describing the need for what is sometimes called 'southbound' authentication. Specifically mutual-TLS sometimes called client authentication, as opposed to standard (or one-way) TLS where only the server is being authenticated by the calling client. You're right: mTLS (a.k.a., "two-way SSL") is one means to allow your back-end server to authenticate the calling Apigee-layer 'client'.
When you want client authentication via TLS (mTLS) you need to configure your back-end server endpoint to require mTLS at the time of the handshake, and to have stored in its Truststore the signing CA certificate of the client certificate you expect to see offered up by the calling client at time of connection. Done right, your server
requires mTLS and shuts down the handshake if the client won't
offer a client cert,
validates the client cert is authentic as being issued by a recognized signing CA (Truststore), and
is the actual client cert expected to be seen (e.g., by matching the expected distinguished name).
Here's an authoritative support-community article about doing all this, within Apigee: https://community.apigee.com/questions/63337/mutual-tls-between-client-to-edge-and-edge-to-back.html

Digital certificate in API response

I'm working on an authentication method for my NodeJS API.
I'm using TLS certificates to verify the client connected to my API server.
My question is: can we have a way to authenticate the response back to the client? Can we use cert for this to(server to client)?
eg: When we call an API from our client we send the certificate with the request which is authenticated and if found valid the server sends the response, can we do it vice-versa, send a certificate in response and have the client validate the certificate.
The whole TLS protocol and the certificates are already built around this idea that you trust the server. I.e. the server during establishing of TLS connection provides a certificate that client can verify by checking if it trusts the CA that has issued the certificate.
Now while this is generally so, you can have libraries that allows to bypass this by not checking the certificate or checking but proceeding anyway, so you have to double check that is not the case. The browser does this automatically.
If you click on a green "Secure" button that is to the left in URL in Chrome e.g. you can click on "certificate" there and see the certificate that is provided by the server. If it's green, then it's trusted and all's good.
P.S. Neither the client not server sends the certificate the whole time back and forth with each request/response. They do it only once during establishing the connection that is called TLS handshake. It's relatively expensive process so you'd better keep the connection.

Self signed client certificate does not reach server application

I have the following setup:
A self signed certificate for development purposes
An OWIN hosted Web API, deployed on a local Azure Service Fabric Cluster as a ASF service. The Web API uses HTTPS facilitated with the dev certificate in question.
A simple .net client application that calls the Web API. In that application the ServicePointManager.ServerCertificateValidationCallback method is set so it always returns true (since the CA is not trusted)
Both the client application and the Web API are on the same local development machine. The certificate is installed in that same machine on the "machine store"
Now I am able to make calls to the web api using Fiddler by providing the required client certificate. However when I try to do the same via .net code (be it RestSharp or WebRequest) the client certificate is not present in the RequestContext object on the server side. This result in an Unauthorized response. I do not think the problem is with the client code, the certificate is loaded correctly and assigned to the http client or request. Fiddler shows encrypted tunneling to the server. However the client certificate does not seem to be present at the server side.
I am at a complete loss regarding what am I missing that could cause this behavior. Any help will be deeply appreciated.
Install the certificate into the 'Local Machine/Trusted People'.
The server needs to already trust the certificate before it asks. The CertificateRequest message that it sends lists the acceptable CAs that can sign the client certificate. If the client certificate's signer isn't in that message, it can't send it.
How you accomplish that in your environment is left as an exercise for the reader. In general now that SSL certificates are available free there is little reason to indulge in the time costs and administrative inconveniences of self-signed certificates. IMHO there wasn't even if you were paying for a CA signature.
I had a problem when a service called another service over HTTPS and it couldn't setup a secure connection. My problem was that since the service is running as NETWORK SERVICE, it couldn't find the certificate, because it was looking in the localmachine/my certificate store.
When I was running from my web browser it was working fine because then, my browser found the certificate in the currectuser/my certificate store.
Add the certificate to the machine/my store and see if it helps.

2 Way SSL - Client Certificate Not Sent To Server

I'm have an application deployed to salesforce on the force.com platform,
which I'm trying to configure a 2 way SSL for.
I.e.
I want that for each request sent to from SF to my server, a client certificate will be sent.
I did the necessary configurations on SF for the certificate to be sent, but I'm still getting 403.7 from the server, which means: forbidden, client certificate required.
I installed wireshark on the server, captured traffic to see the 2 way ssl handshake, and I'm trying to find in the server hello message where it tells the client the trusted CAs from which a client certificate should correspond, but I'm having difficulties finding it.
I suspect that's why the client does not send the certificate.
Can anyone point me to where in the server hello I should look? Or perhaps in another packet capture?
Thanks in advance.
Client Key Exchange record:
Here, the server sends its Certificate Request message and the client sends its Certificate message in response, but that message contains 0 certificates.
Typically, this happens when the client was unable to select a client certificate to use. Either it's not configured properly to make use of any certificate, or it can't find one that is issued by one of the acceptable CAs.
Look at the Certificate Request packet and check its certificate_authorities list. This is a list of the CA Distinguished Names (DNs) that the server is willing to accept.
One way or another, the client will need to find a client certificate with which it can build a chain towards of those DNs. In the simplest case, a client certificate issued by such a DN is available. Otherwise, the client could have to build a chain from a client cert to such a DN, it would need to have the necessary intermediate CA certificates to do so. (How this is done depends on the client's configuration mechanisms.)
If intermediate CA certificates are necessary and not available on the client side, you may need to configure your server to accept them and advertise them in the Certificate Request too.
Added a screenshot of the handshake captures. can you please point me to where I should be looking? –
See packet #31. It contains the Certificate Request. Also packet #33 contains the certificate from the client, so the reason is not the client does not send the certificate, but instead that the server either does not like the certificate because the validation failed or because the certificate is not sufficient as authorization for the requested resource. You might get more information from the servers log.
Not sure if this will help anyone else, but for our case of this issue everything was working when running locally in Visual Studio and in IIS, but when deployed to a real server, we were hitting a certificate issue during 2-way SSL as described above and verified in Wireshark.
Anyway, on that server we have also have a .NET 4.7.2 Console application which was calling the same API and everything was working fine.
But, our .NET 4.7.2 web API calls were failing. It appears that when the same code was running inside IIS the cert was not available during the SSL negotiation. (although it loaded fine)
Our solution at this point was to modify the following call to include the 3rd parameter.
certificate = new X509Certificate2(certificatepath, Password, X509KeyStorageFlags.MachineKeySet);
By default X509Certificate2 uses the UserKeySet option, so perhaps the application pool user or another thread in IIS (?) was having trouble accessing the cert for the negotiation.
Here are a couple of the related pages that I found useful during my research:
https://paulstovell.com/x509certificate2/
https://github.com/dotnet/runtime/issues/23437