How to respond to OCSPRequest when using a self signed certificate? - node.js

I'm trying to create an https server using a self signed certificate, but it seems to fail because it requires a response to the OCSPRequest callback, which I have no idea what that should contain. The documentation (https://nodejs.org/api/tls.html#tls_event_ocsprequest) is not helpful at all in my case, especially this part:
Server extracts the OCSP URL from either the certificate or issuer and performs an OCSP request to the CA.
How do I extract the OCSP URL? Do I even need to do that? What/who is the CA? Certificate Authority? No idea, I guess that's me in this case because I created the certificate myself, correct? How do I proceed?
const fs = require("fs");
const httpsServer = require("https").createServer({
key: fs.readFileSync("./key.pem"),
cert: fs.readFileSync("./cert.pem"),
});
const server = httpsServer.listen(9777);
server.on('OCSPRequest', (certificate, issuer, callback) => {
let response = 'What goes in here?';
callback(null, response);
});
All the examples that I found never mention it, for instance: https://nodejs.org/en/knowledge/HTTP/servers/how-to-create-a-HTTPS-server/

A self-signed certificate cannot be revoked, since the issuer of the certificate is the certificate itself. No revocation possible means no OCSP response. The expected behavior based on the documentation you've linked to is thus:
Alternatively, callback(null, null) may be called, indicating that there was no OCSP response.

Related

MTLS - generate certificate to nodejs client side

We need to communicate between our ec2 server and our customer server via Mutual TLS.
The requests are sent from our server to our customer server - so we are the client here.
I read this post, talking about how to generate the files.
The first step is to create a certificate authority (CA) that both the
client and server trust. The CA is just a public and private key with
the public key wrapped up in a self-signed X.509 certificate.
Our cert and their cert - should be signed from the same root CA? who should provide it?
The code in my side should be like:
const req = https.request(
{
hostname: 'myserver.internal.net',
port: 443,
path: '/',
method: 'GET',
cert: fs.readFileSync('client.crt'),
key: fs.readFileSync('client.key'),
ca: fs.readFileSync('ca.crt')
},
res => {
res.on('data', function(data) {
// do something with response
});
}
);
So what should we provide each other? We don't exactly understand and they are not providing more details, just asked us to give them a certificate...
Our cert and their cert - should be signed from the same root CA? who should provide it?
Since the control of the client certificate is done at the TLS server side (i.e. at the customer) it depends fully on what they expect. They might require a publicly signed certificate, they might require a certificate signed by their own CA. Or they might simply check that a specific certificate gets used and will also accept self-signed certificates for this.

validate https requests using a Certificate Authority (CA)

I have deployed multiple microservices containing frontend application and backend service.
The frontend application is accessible via xyz.com domain. It calls the backend service API endpoint.
So, what I really want is to check is that if any request that is coming from the frontend application is valid and from authentic source on the basis of its domain and subdomain using Certificate Authority in Node.js.
After doing a little bit of research about how it can be done in node.js,
I found out that it can be done using nodejs https module's request method. But the problem with this approach is that nodejs maintains a list of CA certs, which easily gets out of date and there is a chance that the CA that has verified my domain certificate is not part of that list. Although they provide a way to pass additional CA's but still it is a dependency on the user side that they have to maintain the list. I am currently a little bit lost on how to do it in a proper way.
I need help on how to do this process easily and efficiently.
There are two ways to validate a domain in node.js
https.request
Nodejs https module's request method validates the domain provided against the chain of Certificate Authorities root certificate. A code example is given below:
var https = require('https');
var options = {
hostname: 'github.com/',
port: 443,
path: '/',
method: 'GET',
rejectUnauthorized: true
};
var ss;
var req = https.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
});
req.end();
req.on('error', function(e) {
console.error(e);
});
rejectUnauthorized: This means that it will validate the server/domain certificate against the chain of CA's root certificate.
The only problem with this approach is that this chain should be updated regularly otherwise a new domain that is signed by a certificate authority root certificate which is not part of the chain, marked as an invalid certificate(a common example is a self-signed certificate).
ssl-validate module
It can also be used but it requires another module to get the domain information.

How to connect with client side certificates using https module on Node.js

In production my website uses a Let's Encrypt certificate, so that the user can see in the browser the valid certificate lock.
If the user navigates to route example.com/dashboard, I would like the login using client side certificate (and not username/password).
I have generated on a server using openssl private & public key. The public key stays on server and the private key is sent to the client.
Using this tutorial, I have created in server.js
const express = require('express')
const https = require('https')
const fs = require('fs')
const masterapp = express()
var options = {
key: fs.readFileSync('/etc/ssl/certs/sslforfree/private.key'),
cert: fs.readFileSync('/etc/ssl/certs/sslforfree/certificate.crt'),
requestCert: true,
rejectUnauthorized: false,
}
And then in the middleware
const cert = req.connection.getPeerCertificate()
if (req.client.authorized) {
if (cert.subject.CN === "Client123" && cert.fingerprint256 === "AA:BB:CC:DD:00..
On Mac OS it shows correctly the prompt in the browser where I select the key (key is stored in Keychain).
Problems:
req.client.authorized is always false
How can I securely check with Node.js that the private key corresponds to public key?
Is it safer to have dashboard.example.com subdomain or route example.com/dashboard (express router)?
According to the medium article you referenced, you need to supply a ca property in the options object. This should be a list of client CAs that you trust:
Finally, we supply a list of CA certificates that we consider valid. For now, we sign client certificates with our own server key, so it will be the same as our server certificate.
, ca: [ fs.readFileSync('server_cert.pem') ]
}
You should use the CA to sign the public key of the client's generated key. To do this, you'll have to generate a CSR with the private key, then sign the CSR with the CA you have in the list. Once you do this, you can send the private key and the resulting certificate to the client in a bundle, and they will be able to authenticate against your system.
This is because you left off the ca property.
This happens between the browser and your server automatically, once you have a trusted ca.
To create a CA, you can use openssl to generate a self-signed certificate and private key.
This depends, and is out of scope for stackoverflow. You might consider asking on serverfault.com or security.stackexchange.com.

NodeJS forwarding client SSL certificates

I am working on Node.js server application which is SSL enabled and accepts client certificates. I am using following code to create https server.
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
ca: fs.readFileSync('ca.pem'),
requestCert: true,
rejectUnauthorized: true
};
https.createServer(options,app).listen(8090, function(){
console.log("Listening on 8090");
});
Other Node.js based client apps are able to connect using their SSL certficate and get the service response.
However from my sever, I want to make another server call and wish to pass on the same client certificate I received. I simply want to forward the same ceritifcate, I understand I can get the certificate details in request object, but how to retrieve the crt and key from that object?
I am looking to do something like below:
app.get('/myservice', (req,res) => {
//req.socket.getPeerCertificate(true);
var agent = new https.Agent({
cert: somelibrary(req.socket.getPeerCertificate(true).??????),
key: somelibrary(req.socket.getPeerCertificate(true).??????),
});
fetch('http://AnotherServiceURL', { method: 'GET' agent}).then(function(response){
res.json(response);
});
});
Is there any library which can convert request certificate details in a way so as to forward those as key and cert? Or is there any other/better way of doing this?
I understand I can get the certificate details in request object, but how to retrieve the crt and key from that object?
While it would be possible to pass the client certificate itself it is impossible to use it again as client certificate in another TLS connection to the final target. For this you would need to have access to the private key of the client, which as the name says is private to the client. As for getting the client certificate (i.e. the public part) see Node.js: access the client certificate.

Load certificate and private key for SSL in Node.js

Sorry but I have no experience with certificates and SSL, especially in Node.js. I need to configure options for express:
var https = require('https');
var options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('csr.pem')
};
https.createServer(options, my_app).listen(3000);
and if I try with self generated certificates (by openssl) all works like a charm.
Now, I need to change the self generated certificates with the true certificates for my domain. In Plesk I have 3 certificates: a CSR, a Private key (.key) and a Certificate (.crt) in text format, and this certificates are already working on the Plesk configuration of my server, so they are ok.
So, what I need to do now? Which of these is the key.pem and which is the csr.pem?
Sorry but I don't know, can anyone explain me?
It should be this:
key: fs.readFileSync('FILENAME.key'),
cert: fs.readFileSync('FILENAME.crt')
CSR is the request you send to the trusted third party to get a signed certificate. You will receive a certificate back from the trusted third party, and that's what you use with the private key in NodeJS.

Resources