Axios Returning "net::ERR_CERT_AUTHORITY_INVALID" - node.js

Currently I have two systems:
A Vultr Server running An Express.js Backend and a Discord Bot (Self Certified SSL)
A Firebase App Running my React App.
The current way the app is set up is the react app is sending a request to the backend (The Express App) using Axios. When I use axios to try to hit an API endpoint on my express app, it returns in the console:
Failed to load resource: net::ERR_CERT_AUTHORITY_INVALID
How do I go about fixing this so I can be able to get the information from my Vultr app using Firebase without getting the Cert Invalid error? Is it Possible? Can I do it using HTTP on my VPS' IP Address while having HTTPS on Firebase? I saw the following circulating but it has not worked:
const instance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
});

The error message is just telling you that your certificate is untrusted.
You've got two choices: trust or ignore
Blindly ignoring ssl errors is very very bad, makes you succetible to man in the middle attacks. The way certificates work is that they delegate their 'trust' to a parent until you reach a CA (Certificate Authority). Let's say you buy a certificate from godaddy, they sign your certificate, so when someone is trying to see if your certificate is valid, they go to godaddy's CA, get the public key and check if your is valid.
If you self sign a certificate there's no CA, hence, no way of trusting it. Unless you explicitly add it to the ca bundle file in your operating system.
Self signed certificates beat no certificates at all, and manually trusting it beats ignoring ssl errors. But, it's a bit of work to catch on with the concepts but it becomes easier with time. If your app is meant for a hobby, ignore away.
Trusting
To trust globally, you would have to get your certificate and add it to the ca trust bundle, which requires you to have access to the OS and admin privileges, which is the casa for your vultr app but not for firebase.
In firebase's case you'd have to fetch the certificates public key and pass it as an argument to axios
here's how
Ignoring
here's how

Related

Why does an Insecure gRPC server still allow connections from secured clients

I can't seem to understand what's happening behind the scene, but any guidance will really be appreciated.
I have the following grpc server that is hosted on Google Cloud Run:
server.js
server.bindAsync(`0.0.0.0:${process.env.PORT}`, grpc.ServerCredentials.createInsecure(), () => { //Notice, this is insecure
server.start();
console.log('GRPC Service Started');
});
Then I was given a service url of the form:
https://test-service-abcdefghij-ue.a.run.app
Then below is a client that connects to the above server using the following code:
client.js
... new test_proto.TestAccount("test-service-abcdefghij-ue.a.run.app", grpc.credentials.createSsl()); //Notice I used createSsl instead of createInsecure()
As you can see from my client code, I used createSsl without passing a self signed certificate, yet the connection to the createInsecure server worked.
I always thought both server and client must provide same self-signed certificates.
So, why does this still work even though the server is configured to be insecure? Does it mean data will still be transmitted in plain text regardless?
Based on comments from #John Hanley posting the answer, Cloud Run does not support client SSL certificates. The client verifies the server's SSL certificate. If a client connects to a Cloud Run service using HTTP (insecure), Cloud Run will redirect the client to an HTTPS endpoint. That means the final connection is encrypted with symmetric encryption. However, encryption alone does not mean a connection is secure. Google Cloud Run also supports IAP to authorize a user's access. In other words, a secure connection requires encryption and authorization.
You can have a look at documentation.

Creating TLS client in Electron desktop app

I am trying to create node server in TLS and create a TLS client in electron, to distribute as desktop application to users. I can add certificates to my TLS server and run it.
But how do I create the client which requires me to insert key and cert in options to create client.
tls.connect(8000, {
key: fs.readFileSync('client-key.pem'),
cert: fs.readFileSync('client-cert.pem')
})
Where do I store the key and cert files? Should it be bundled along with the downloaded electron app?
If the key and cert can be read unpacking the application, doesnt it makes security compromised?
If the key and cert are stored in electron bundle, its going to be same key and cert for every one downloading the application, doesnt it makes security compromised?
If the key and cert are stored in electron bundle, how do I update the certificate(when changed in the server) after user downloads the application?
I worked based on this link
https://github.com/nodejs/help/issues/253
It would be great if someone can point me in the right direction.
We are facing websocket blocked for some users, so we are trying to use TLS duplex socket.
It looks like I dont need client certificate after all in my case. Seems I can authenticate with auth token or username/password. This one way TLS will be offering the full socket encryption to prevent Man-in-the-middle attack.
Incase of using self signed certificates as in example above, supplying CA certificate alone can suffice to make it work for POC stage.
tls.connect(8000, {
ca: fs.readFileSync('ca.crt')
})
The following materials helped in arriving to my conclusion:
https://chat.stackoverflow.com/rooms/118168/discussion-between-castaglia-and-agm
https://stackoverflow.com/a/8230650/5384225
https://crypto.stackexchange.com/a/406/75660
Still I dont have answers for the original questions I had asked.

Can I use Client Certificates on Azure App Services without a custom domain?

For testing purposes I would like to enable the 'Incoming Client Certificates' option in my Azure App Service (running a WCF webservice), and see if my Client application can still connect to the webservice. Since I am still in a testing phase, my app service still has the .azurewebsites.net domain name.
However, I can't seem to figure out how to get a proper client certificate that the server will accept (without switching to a custom domain name, which I know will work).
Currently, I see 2 possible routes to a solution:
Somehow get my hands on .cer that is signed by a CA trusted by the App Service server.
Generate a self-signed .pfx and .cer with my own self-signed CA. Import the pfx on the App Service and install the .cer on the client.
Both directions have not yielded any success so far. Does anyone have any experience with this?
Per my understanding, the client certificate is used by client systems to make authenticated requests to a remote server. In this case, your webservice is the remote server in a C/S mode. As you point out, "validating this certificate is the responsibility of the web app. So this means that any certificate will be valid as long as you don't validate anything". It does not effect on whether you have a custom domain or not in your web app service.
If you want to use client cert authentication with Azure app, you can refer to How To Configure TLS Mutual Authentication for Web App.
If the server has requested client certificate in its server hello and the client cert has signing capability, then it is expected to send the CertificateVerify message to the server. It contains signed hash of all messages from Client Hello till that point which are buffered on the server side. The server TLS layer will decrypt this using the client public key (which is in the Client certificate received earlier) and compare with its calculated hash. It will call back to application layer if this fails.
The application needs to handle it at that point and return its own error or continue with the session. https://www.rfc-editor.org/rfc/rfc5246#section-7.4.8
One example of this with Wolfssl library is https://github.com/wolfSSL/wolfssl/blob/14ef517b6113033c5fc7506a9da100e5e341bfd4/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs#L145

Azure App Service using Self-Signed Cert

I deployed an application out to our app service in Azure, and the app needs to have SSL to run, but since it is still in development I did not want to have to purchase a cert yet, so I created a self-signed cert through openssl. The private key is 2048 bits, which should be enough, but when I go to apply the cert to the hostname, it just sits there and never applies.
Is there a special step you have to complete to get self signed certs to work, or, are you not allowed to use self signed certs in Azure App Services?
Try to use ServerCertificateValidationCallback to monitor the verification of server certificate, comparing the certificates between local and server or just returning true.
Now when you invoke the https service in your web app, the verification callback will be invoked automatically. If failed, you will see the errors. If successful, the service response will be returned.
For more details refer this article: http://devchat.live/en/2017/09/29/how-to-invoke-https-service-protected-by-self-signed-certificate-from-azure-app-service/.

Securing Service calls from node using ssl

I am trying to securing the service calls that are made from my node to other services secure. All the other services have enabled https. I tried the following methods
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
which as per my understanding ignores all error so removed from the code becuase of certificates
I am using request module. where we can configure
key - provided my private key file,
cert - provided my certificate file
ca - certificate authorty chain
then it was throwing UNABLE_TO_VERIFY_LEAF_SIGNATURE
I found out that node doesn't read ca from the system.
it has its own ca chain So I included node-ssl-root-cas
which fetched latest cas from internet.
Then using ssl-analyser, i was able to find my domain doesn't have intermediate ca certificate
I downloaded that from our ca and made a ca chain and attached it to ssl-root-cas
Then i was able to make requests successfully
But Even if I remove key and cert from my request i am able to make request and get result.
How can I check my request and response are actually encrypted?
Or node just ignoring errors,
FYI, Node will use the certificate auhtorities installed on the system if you don't provide your own with the "ca" property. When you do provide your own, the system ones are ignored. This is by design, as providing your own CA likely means that you want to only trust certificates signed by your own CA. If you aren't using your own CA, you can skip setting the "ca" property. If you are, then I'm not sure why you would need to provide the full list of commonly trusted CAs as well. That seems like a pretty odd use case.
You can use the https module to make requests without providing your own key and cert. This is expected and documented behaviour. For technical reasons, when making any https requests, more specifically opening any TLS socket, the client also needs to have a private key and certificate. In the default case, the server doesn't verify the client in any way, so browsers use what's commonly referred to as a "snakeoil" certificate - a bundled self signed certificate.
The use case for providing your own key and cert when performing https requests, is when the server has client certificate checks enabled. For example, when connecting to Apple's servers for delivering push messages to iOS, you have a client certificate issued by Apple that Apple's servers uses to verify that you have access to send push messages (the certificate was issued by Apple) and which app you are sending to (the fingerprint/checksum of the certificate).
Unless the https services you talk to require specific client certificates, you're better off not setting "key" and "cert" - there's no real reason to do that.
So, in summary, you can probably skip setting all three of key, cert and ca, as the real problem seemed to be your mis-configured server (it didn't serve the CA chain).

Resources