I've been trying to do a test about TLS connection between server and client. (SSL-Client Authentication)
I have a self-signed key pair.
If I try to connect my API server using tls.connect(), my connection seems as unauthorized and authorizationError value is UNABLE_TO_VERIFY_LEAF_SIGNATURE as shown the below screenshot.
However, if I try to connect https://api.twitter.com instead of https://hellolarim.club then there is no error and authorization value is true. Also when I trying to Twitter I don't have to use rejectUnauthorized: false parameter.
I added the below server.jscodes too.
Question: I'm wondering that why I cannot connect as authorized: true ?
I have to implement SSL-Client Authentication to my API server.
The attempt to connect to my API server
client.js
var tls = require('tls');
var fs = require('fs');
var options = {
key: fs.readFileSync('client-private-key.pem'),
cert: fs.readFileSync('client-certificate.pem'),
rejectUnauthorized: false,
};
{
var cleartextStream = tls.connect(443, 'www.hellolarim.club', options, function() {
console.log('\nclient connected', cleartextStream.authorized ? 'authorized' : 'unauthorized');
if(!cleartextStream.authorized) {
console.log("authorizationError: " + cleartextStream.authorizationError);
}
process.stdin.resume();
process.stdin.pipe(cleartextStream);
});
cleartextStream.setEncoding('utf8');
cleartextStream.on('data', function(data) {
console.log("\n" + data);
});
cleartextStream.on('end', function() {
server.close();
});
The attempt to connect to Twitter API server
Server.js
var tls = require('tls');
var fs = require('fs');
var options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
requestCert: true,
rejectUnauthorized: true,
ca: [ fs.readFileSync('../client/client-certificate.pem') ]
};
var server = tls.createServer(options, function(cleartextStream) {
console.log(cleartextStream.getPeerCertificate());
console.log('server connected',
cleartextStream.authorized ? 'authorized' : 'unauthorized');
cleartextStream.write("Hello from server to client!\n");
cleartextStream.setEncoding('utf8');
cleartextStream.pipe(cleartextStream);
});
server.listen(443, function() {
console.log('server bound');
});
The problem is on client side.
Client cannot recognize server's certificate despite the certificate had been gotten from a commercial CA because there is no ca parameter on client options!
And if we have a lot of root certificates we can install them by transforming a string array like the below or use node-ssl-root-cas.
var CAcerts = [
// A Root CA cert.
"-----BEGIN CERTIFICATE-----\n" +
"MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE\n" +
"BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG\n" +
"tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW\n" +
"sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp\n" +
"7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I\n" +
"LaZRfyHBNVOFBkpdn627G190\n" +
"-----END CERTIFICATE-----\n",
// Another Root CA cert.
"-----BEGIN CERTIFICATE-----\n" +
"MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE\n" +
"BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG\n" +
"tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW\n" +
"sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp\n" +
"7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I\n" +
"LaZRfyHBNVOFBkpdn627G190\n" +
"-----END CERTIFICATE-----\n"
];
var options = {
key: fs.readFileSync('client-private-key.pem'),
cert: fs.readFileSync('client-certificate.pem'),
ca: CAcerts,
requestCert: true,
rejectUnauthorized: true,
};
Related
I am trying to add an SSL certificate to my Nodejs website.
const fs = require('fs');
const https = require('https');
const options = {
key: fs.readFileSync('./ssl/private.key', 'utf8'),
cert: fs.readFileSync('./ssl/certificate.crt', 'utf8'),
requestCert:true,
rejectUnauthorized: false
};
var server = https.createServer(options, app);
app.listen(process.env.PORT || 443, () => {
console.log('Server is running on 3000!')
})
The app does not throw any error but if I try to connec, I still get the connection is not secure in chrome.
I changed my code to:
https.createServer({
key: fs.readFileSync('./ssl/private.key'),
ca:fs.readFileSync('./ssl/ca_bundle.crt'),
cert: fs.readFileSync('./ssl/certificate.crt')
}, app).listen(443);
and it worked
I have a NodeJS websocket client app, using ws https://www.npmjs.com/package/ws - this NodeJS app connects as a client to a websocket server.
I can use HTTPS by specifying wss:// as the protocol.
How can I make the TLS connection use a client certificate for authentication?
i.e. the websocket client should use a certificate to prove its identity to the server.
I found:
it('connects to secure websocket server with client side certificate', function(done) {
const server = https.createServer({
cert: fs.readFileSync('test/fixtures/certificate.pem'),
ca: [fs.readFileSync('test/fixtures/ca1-cert.pem')],
key: fs.readFileSync('test/fixtures/key.pem'),
requestCert: true
});
let success = false;
const wss = new WebSocket.Server({
verifyClient: (info) => {
success = !!info.req.client.authorized;
return true;
},
server
});
wss.on('connection', () => {
assert.ok(success);
server.close(done);
wss.close();
});
server.listen(0, () => {
const ws = new WebSocket(`wss://localhost:${server.address().port}`, {
cert: fs.readFileSync('test/fixtures/agent1-cert.pem'),
key: fs.readFileSync('test/fixtures/agent1-key.pem'),
rejectUnauthorized: false
});
});
});
on https://github.com/websockets/ws/blob/14d9088391ac4495d04e64d76c3b83d4e75f80e2/test/websocket.test.js
I'm running NodeJS with TLS and have created a server like so:
const tls = require('tls');
const fs = require('fs');
const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
rejectUnauthorized: true,
requestCert: true,
ca: [ fs.readFileSync('clientX-cert.pem') ]
};
const server = tls.createServer(options, (socket) => {
console.log('server connected', socket.authorized ? 'authorized' : 'unauthorized');
socket.on('data', function (data) {
socket.write(data);
});
});
server.listen(5000);
I'm trying to only approve client with a specific client certificate clientX-cert.pem, but it seems to fail as my client is getting an Error: socket hang up at his end.
When not having requestCert it does work, but then everyone is allowed with a TLS certificate.
Have I misunderstood the rejectUnauthorized: true, requestCert: true and ca: options?
Example Program:
Server:
var fs = require('fs');
var https = require('https');
var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-crt.pem'),
ca: fs.readFileSync('ca-crt.pem'),
};
https.createServer(options, function (req, res) {
console.log(new Date()+' '+
req.connection.remoteAddress+' '+
req.method+' '+req.url);
res.writeHead(200);
res.end("hello world\n");
}).listen(4433);
Client:
var fs = require('fs');
var https = require('https');
var options = {
hostname: 'localhost',
port: 4433,
path: '/',
method: 'GET',
ca: fs.readFileSync('ca-crt.pem')
};
var req = https.request(options, function(res) {
res.on('data', function(data) {
process.stdout.write(data);
});
});
req.end();
I have generated the Keys and certificate using openssl in my Linux server.
But while running client program its showing as Error: self signed certificate . By referring some websites and even stack overflow discussions some have mentioned that using a option called rejectUnauthorized: false even though there is no use in using this parameter while using certificates for secure transfer of data.
Is there any way to trust the certificates in Linux server?
Any example program with certificates and node JS Program ?
Node JS Client to connect to server?
Without Using rejectUnauthorized: false?
I am trying to get both ws and wss working, on one WebSocket server.
This is what I currently have, only wss
var WebSocket = require('ws');
var https = require('https');
var privateKey = fs.readFileSync('cert/key.key');
var certificate = fs.readFileSync('cert/cert.crt');
var httpsServer = https.createServer({
ca: ca,
key: privateKey,
cert: certificate
}, this.app);
var options = {
server: httpsServer,
perMessageDeflate: false,
maxPayload: 4096
};
var wss = new WebSocket.Server(options);
I know using Socket.io it is really easy, you can just do io.attach(httpServer) and io.attach(httpsServer).
var httpServer = http.createServer(this.app);
var httpsServer = https.createServer({
key: privateKey,
cert: certificate
}, this.app);
httpServer.listen(3002, function(){
console.log('httpServer listening on port 3002');
});
httpsServer.listen(3003, function(){
console.log('httpsServer listening on port 3003');
});
this.io = new ioServer();
this.io.attach(httpServer);
this.io.attach(httpsServer);
Is this even possible, using this WebSocket library?