nodejs, make https request to backend server - node.js

Using https request, I was trying to connect to backend server using the below documentation guide:
http://nodejs.org/api/https.html#https_https_request_options_callback
function getHttpsReq (request, response)
{
var options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
rejectUnauthorized: false,
strictSSL: false,
agent: false,
method: 'GET'
}
https.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
var data = '';
res.on('data', function(d) {
process.stdout.write(d);
data += data + d;
});
res.on('end', function() {
console.log("Done");
response.end(data);
});
});
}
But when I am trying this, it is throwing the below error:
Error: 140735290610048:error:0607907F:digital envelope
routines:EVP_PKEY_get1_RSA:expecting an rsa
key:../deps/openssl/openssl/crypto/evp/p_lib.c:288:
$ node --version
v0.8.15
Please let me know what I need to do extra?

What you need are the certificates to your domain.
This can be added using the below code.
key: fs.readFileSync('/etc/apache2/ssl/domain.key'),
cert: fs.readFileSync('/etc/apache2/ssl/domain.crt')
to your options.
The certificates can be obtained using a trusted authority or you can use self signed certificates. But self signed certificates would generate an error on client's side if it is not added to the trusted certificates in client's machine.

Related

NodeJS Error: header too long at Object.createSecureContext

I am trying to call the REST API with PFX & PassPhrase, but each time I getting 'header too long' error.
My certificate file size is 11kb. Below snippet is working fine for other REST API without pfx, but no success with pfx
var options = {
hostname: '<hostname>',
port: 443,
path: '/',
method: 'POST',
pfx: fs.readFileSync(<pfx file path>),
passphrase: '<passphrase>',
json: { 'Request': 'My Custom Req'}
};
var req = https.request(options, function (res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
res.on('data', function (d) {
process.stdout.write(d);
});
});
req.end();
req.on('error', function (e) {
console.error(e);
});
I have ran my application with following command; but still problem persists:
node --max-http-header-size=819200 .\restPost.js
The REST API is perfectly working and I have tested the same using Postman and .NET Core web client solutions.
Need your help to fix the issue in NodeJS

IBM - Creating a VPC using API with Node.js

I have a Node.js application which currently allows the user to provision a Digital Ocean Droplet. However, I'm now trying to migrate over to IBM Cloud and instead want to provision a Virtual Server.
The issue I'm having is I have no experience working with APIs. Digital Ocean has its own NPM package acting as a wrapper over the Digital Ocean API bit I can't find an equivalent for IBM Cloud. I've been looking through the VPC API documentation and I have gone through the entire process of creating a Virtual Server using the terminal and I've successfully provisioned a Virtual Server.
Now, I'm trying to get these cURL requests to work in Node.js. I'm starting with just the simple GET images API to try and print the available images. The command looks like this:
curl -X GET "https://eu-gb.iaas.cloud.ibm.com/v1/images?version=2019-10-08&generation=1" \
-H "Authorization: *IAM TOKEN HERE*"
I've read over the Node HTTP documentation and so far I've converted this command to look like this:
const http = require('http')
const options = {
hostname: 'https://eu-gb.iaas.cloud.ibm.com',
port: 80,
path: '/v1/images?version=2019-10-08&generation=1',
method: 'GET',
headers: {
'Authorization': '*IAM TOKEN HERE*'
}
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
req.end();
However, when I run the JS file, I get the following error:
problem with request: getaddrinfo ENOTFOUND https://eu-gb.iaas.cloud.ibm.com https://eu-gb.iaas.cloud.ibm.com:80
Can someone please explain to me the error, where I'm going wrong, and how I can fix this issue?
Many thanks in advance,
G
try as below:
const https = require('https');
const options = {
hostname: 'eu-gb.iaas.cloud.ibm.com',
port: 443,
path: '/v1/images?version=2019-10-08&generation=1',
method: 'GET',
headers: {
'Authorization': 'Bearer <IAM TOKEN HERE>'
}
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error(e);
});
req.end();
The protocol http:// shouldn't be included in the host field, also, it is recommended the use of https.

Node.js: access the client certificate

I'm working on a Node.js app that we will call "server A" where users have to provide a client certificate in order to access services.
Simplified example:
/** server setup **/
var serverOptions = {
key: fs.readFileSync('certs/server.key'),
cert: fs.readFileSync('certs/server.crt'),
ca: [fs.readFileSync('certs/ca.crt'), fs.readFileSync('certs/bar.cer'), fs.readFileSync('certs/foo.cer')],
requestCert: true
};
https.createServer(serverOptions, app).listen(SERVER_PORT, '', null, function () {
var host = this.address().address;
var port = this.address().port;
console.log('listening at http://%s:%s', host, port);
});
Everything works as expected, the following code prints the details of the client certificate.
app.get('/', function (req, res) {
/*** Dump ***/
res.contentType('application/json');
res.send(util.inspect(req.socket.getPeerCertificate(true), {colors: true}));
});
However, I would like to be able to use this client certificate obtained in serverA, to make a request to another server called "server B".
options = {
hostname: 'localhost',
port: '3010',
path: '/',
method: 'POST',
headers: {
'Content-Type': 'text/xml;charset=UTF-8',
'Content-Length': serverResponse.length,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
},
cert: clientCertificate
};
var req = https.request(options, function (res) {
console.log('statusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', function(d) {
callback(d);
});
});
The problem is that I have not found a way to get a proper X509 certificate with the getPeerCertificate function, which returns a "custom" object representation of the certificate.
As described in the official documentation, the cert parameter must be provided with the following data :
Public x509 certificate to use. Default null.
Is there a way to get the client certificate in the correct format for that purpose?
I had the same problem and saw your question with no answers, so I'm coming back to post my solution.
The certificate object has a raw field which contains the certificate data you want in byte form. To get it in X509 format, just convert it to base64. So the code you're looking for is:
req.socket.getPeerCertificate(true).raw.toString('base64');
Hope that helps!

Verify ssl certificate in nodejs

How can I verify SSL certificate on https of given domain by NodeJS?
I need to know if user open this like is it trusted or should add it as exception?
--
I think this code should raise error during unsigned or selfsigned certificate.
var https = require('https');
var options = {
host: 'daarkoob.ir',
port: 2222,
path: '/',
method: 'GET',
rejectUnauthorized:true
};
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);
});
https://daarkoob.ir:2222 is self signed certificated,so above code should raise error during surfing.but nothing happened.
From the documentation:
rejectUnauthorized: If true, the server certificate is verified against
the list of supplied CAs. An 'error' event is emitted if verification
fails. Verification happens at the connection level, before the HTTP
request is sent. Default true.
I guess that you need to specify a list of CA or the option is ignored.

How do I avoid SELF_SIGNED_CERT_IN_CHAIN error in node.js TLS module?

I am trying to create a TLS/SSL connection using node.js v0.10.5 and the einaros/ws (WebSockets) module, but I get the following error:
Error: SELF_SIGNED_CERT_IN_CHAIN
I get my cert from my own CA, which is an EJBCA server, Version : EJBCA 4.0.15 (r16671) and I am using the following code in my client:
define(["ws", "fs"], function (WebSocket, fs) {
"use strict";
return function (jsonRequest) {
var response,
error,
successCallback,
errorCallback,
HB_PFX = "server.domain.com.p12",
HB_CA = "certs/my-ca.pem";
var secureOptions = {
passphrase: "the-passphrase",
pfx: fs.readFileSync(HB_PFX),
ca : [fs.readFileSync(HB_CA)]
};
var sendRequest = function () {
var client = new WebSocket("wss://server.domain.com:8080/draft", secureOptions);
client.on("open", function () {
client.send(jsonRequest);
});
client.on("error", function (e) {
error = e.toString();
console.log(error);
if (errorCallback) {
errorCallback(error);
}
});
client.on("message", function (message) {
response = message;
if (successCallback) {
successCallback(message);
}
});
client.on("close", function (code) {
console.log("Connection closed with code: " + code);
});
};
return {
send: function (callback) {
if (response && !error) {
callback(response);
} else {
successCallback = callback;
}
sendRequest();
return this;
},
ifError: function (callback) {
if (error) {
callback(response);
} else {
errorCallback = callback;
}
return this;
}
};
};
});
The p12 store (PKCS12) is generated by the CA, and it includes the key, my server certificate, and the CA certificate.
I can connect to the server with a browser with no problems, I just get prompted to accept the certificate on first connection. But when I try to connect with my client, I always get that error. I am connecting to the server using its FQDN, not an IP address.
If I try to use a self-signed certificate (a cert generated in my local machine and used instead of the p12 file), I get a DEPTH_ZERO_SELF_SIGNED_CERT error.
I am running on Mac OS X 10.8.4.
I have tried almost every permutation, even exporting the key and certificates from the PKCS12 file to PEM files, but I get the exact same error. I have also added the CA certificate to all the cacert files that I could find in my computer, which are the following:
/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java/lib/security/cacerts
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts
/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/security/cacerts
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/cacerts
/System/Library/Java/Support/CoreDeploy.bundle/Contents/Home/lib/security/cacerts
/System/Library/Java/Support/Deploy.bundle/Contents/Home/lib/security/cacerts
Does anybody know how to solve this error and create secure connections in node?
Does anybody know how to solve this error and create secure connections in node?
For the case of Mac OS X, you need to put the root certificate (self signed, used for signing) in your Keychain.
check with this
npm config set ca ""
more info here
https://github.com/gootyfer/simple-ws-bradcast-server
The following is the https_server and client which i created as sample, take a look if this helps you.
https_server.js
var https = require('https');
var fs = require('fs');
var url = require('url');
var options = {
key: fs.readFileSync('privkey.pem'),
cert: fs.readFileSync('cacert.pem')
};
https.createServer(options, function (request, response) {
var url_parts = url.parse(request.url, true);
var query = url_parts.query;
console.log("----------------------------------");
console.log(request.method + " method" + " and " + " timeout is "+ query.timeout);
setTimeout(function () {
console.log(" Executing setTimeout Function ");
if(request.method=='POST') {
console.log(" Inside post " );
var body='';
request.on('data', function (data) {
body +=data;
});
response.setHeader("keyPOST","ValuePair");
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<b>Hello World</b>");
response.end();
request.on('end',function(){
var POST = qs.parse(body);
console.log("on request end " +POST);
console.log("----------------------------------");
});
}
else if(request.method=='GET') {
console.log(" Inside get" );
console.log("Query sent to the server is :" +query.name);
response.setHeader("keyGET","ValuePair");
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<b>Hello User, Response sent at "+query.timeout+" milli seconds from server</b>");
response.end();
request.on('end',function(){
console.log("on request end");
console.log("----------------------------------");
});
}
}, query.timeout);
}).listen(8000, "127.0.0.1",function() {
console.log(' Server has been started at '+(new Date()) +' and running in https://127.0.0.1:8000/');
});
https_client.js:
var https = require("https");
var fs = require("fs");
var querystring = require('querystring');
var data = querystring.stringify({
name: "Arun",
timeout:5000
});
var options = {
hostname: '127.0.0.1',
port: 8000,
path: '/saveText?name=Arun&timeout=5000',
method: 'GET',
key: fs.readFileSync('privkey.pem'),
cert: fs.readFileSync('cacert.pem'),
agent: false,
rejectUnauthorized: false
};
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
//req.write(data);
req.end();
create privkey.pem and cacert.pem using openssl :
1) command to create privkey.pem is : openssl genrsa -out privkey.pem 2048
2) command to create cacert.pem is : openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095
(or) if the second command shows unable to locate openssl.cnf error use -config {openssl.cnf file path} option along with second command.

Resources