how to configure https in sails.js - node.js

I am trying to setup a local HTTPS server for testing in Sails.js? I am not able to find any pointer how to do that in sails.js? For express,
var express = require('express');
var https = require('https');
var http = require('http');
var fs = require('fs');
// This line is from the Node.js HTTPS documentation.
var options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
// Create a service (the app object is just a callback).
var app = express();
// Create an HTTP service.
http.createServer(app).listen(80);
// Create an HTTPS service identical to the HTTP service.
https.createServer(options, app).listen(443);
Any idea about sails.js?

For sails.js version 0.10, include this in config/locals.js (if locals.js does not exist, create it):
var fs = require('fs');
module.exports = {
ssl : {
key: fs.readFileSync('path-to-key.key'),
cert: fs.readFileSync('path-to-crt.crt')
}
};
Source: https://stackoverflow.com/a/28565113/2459071

If you're using the latest v0.9 (and maybe some versions of v0.8) take look inside of config/bootstrap.js. You should be able to access your express app via the sails.express context. From there I think you should be able to do with it what you want to...
Also someone in the #sailsjs irc channel said this worked for them
module.exports.bootstrap = function (cb) {
var fs = require('fs');
sails.config.express.serverOptions = {
key: fs.readFileSync('ssl/key.pem'),
cert: fs.readFileSync('ssl/cert.pem')
};
cb();
};

Maybe it's just me but I could get either of the above working for sails v0.9.7, but I did get it working by editing the config/local.js file like so;
var fs = require('fs');
module.exports = {
port: process.env.PORT || 1337,
environment: process.env.NODE_ENV || 'development',
express: { serverOptions : {
key: fs.readFileSync('ssl/key.pem'),
cert: fs.readFileSync('ssl/cert.pem')
}
}
};
Now I'm not saying this is the 'correct' way to do this, however it works for me!
Shameless self promotion
More about this on my blog!
End shameless self promotion :D

This contribution enhances the solution for to support native mobile applications and old browsers.
This solution worked really well for me when when just using a modern web browser to access my SSL site. However when I attempted to make requests using the AFNetworking library it did not recognise the SSL certificate. This was due to the iPhone application requiring the intermediate SSL certificates (sometimes called the ca bundle).
You can add the intermediate certificate in using the following code.
express: {
serverOptions : {
key: fs.readFileSync('ssl/key.pem'),
cert: fs.readFileSync('ssl/cert.pem'),
ca: fs.readFileSync('ssl/intermediate.pem')
}
}
When creating you intermediate certificate (which can normally be downloaded from your SSL certificate provider) it is important to get the order of certificates right.
This linux command really helped with debugging.
openssl s_client -connect yoursite.com:443 -showcerts

The above does not work for sails v0.9.3. I ended up with the following workaround. (require fs first of course)
express : {serverOptions : {
key: fs.readFileSync('ssl/server-key.pem'),
cert: fs.readFileSync('ssl/server-cert.pem'),
}}

I have also faced this kind of issues in my production sails app (v0.11.x and v0.12.x). Android release version apk is not able to connect to sails app and some old version browsers do not accept SSL certificate with web app.
I got some intermediate certificate error like below
The certificate is not trusted in all web browsers. You may need to install an Intermediate/chain certificate to link it to a trusted root certificate.
Finally, I found a solution
ssl: {
ca: require('fs').readFileSync('ssl/intermediate.crt', 'utf8').toString(),
key: require('fs').readFileSync('ssl/example_com.key', 'utf8').toString(),
cert: require('fs').readFileSync('ssl/main.crt', 'utf8').toString()
}
I hope this will help someone.

Related

Node httpAgent with proxy and certificates (https-proxy-agent with TLS)

So I'm trying to make a call inside my node test (AVA) that uses proxy and TLS authorization.
I'm using:
typescript: 3.9.3
ts-node: 8.10.2
axios: 0.21.1
https-proxy-agent: 5.0.0
What I've learnt so far:
AxiosProxyConfig is broken at the moment so I cannot use it:
Axios proxy is not working,
https-proxy-agent is indeed working as it was said by kraiz in bug thread, but... I cannot see anything about ca, cert and key I cannot provide those I was not able to find any docs except this one https-proxy-agent npm page.
So just to wrap up with some code, that's what I'm trying to do and I have no idea how to achieve that:
const httpsProxyAgent = new HttpsProxyAgent({
cert: this.cert,
key: this.key,
ca: this.ca,
host: PROXY_HOST,
port: PROXY_PORT,
});
// then later
const config: AxiosRequestConfig = {
httpsAgent: httpsProxyAgent,
headers: { ... }
proxy: false
};
Though HttpsProxyAgent seems to extend Agent those options (certs part) are not used and I get UNABLE_TO_VERIFY_LEAF_SIGNATURE error that indicates that ca is ignored.
Does anyone knows how to provide those certs to this agent?
I couldn't find any answers. I'm not a node expert so I might have missed something obvious.
Thanks in advance!
PS. I've also tried Objects.assign() like this
// this proxy agent is working for sure (tested)
const httpsProxyAgent = new HttpsProxyAgent('http://proxy:1234');
// trying to assign certs after creating httpsProxyAgent
Object.assign(httpsAgent.options, {
ca: this.ca,
key: this.key,
cert: this.cert
});
// then again passing it to AxiosRequestConfig.httpAgent and making a call
result was once again UNABLE_TO_VERIFY_LEAF_SIGNATURE.
PSS. I've seen this better-https-proxy-agent (git page) that seems to have solution, the only drawback is I cannot see any TS support.

Firebase hosting + custom server are incompatible?

My expressjs+Socket.io server runs on a Raspberry Pi. When trying to connect to the express, there is a http+https incompatibility that Firebase doesn't seem to like. Tells me to use Https instead. When using Https, I get Certificate errors. So I went and bought myself a brand new SSL certificate from my domain provider and... on my local machine, where I accidentally installed the certificate, everything works fine, but on my laptop or mobile, when I go to the website, it says "(net::ERR_CERT_COMMON_NAME_INVALID)". I am not sure what to do, since many resources online cover only how to bypass this problem on their machine, without fixing the problem for everyone.
Server.js
var app = require("express")();
var https = require("https");
var fs = require("fs");
var server = https.createServer(
{
key: fs.readFileSync('./sslkey.key'),
cert: fs.readFileSync('./sslcert.crt'),
ca: fs.readFileSync('./sslca.ca-bundle'),
},
app
);
var io = require("socket.io")(server);
io.on("connection", function(socket) {
console.log("User connected");
})
server.listen(4444, function() {
console.log("listening on *:4444");
});
I also use Socket.io with Angular and I couldn't find a way to disable "rejectUnauthorized", as many suggested to skip the SSL check.
Any help?

SocketIO throws net::ERR_CERT_AUTHORITY_INVALID on self signed certificate

I am using socket io on client:
const socket = require('socket.io-client')('https://localhost:4200', {secure: true, rejectUnauthorized: false})
And on server:
let https = require('https')
let fs = require('fs')
let options = {
key: fs.readFileSync('cert/my.net.key'),
cert: fs.readFileSync('cert/my.net.cert'),
requestCert: false,
rejectUnauthorized: false,
};
const server = https.createServer(options, require('express')())
const io = require('socket.io')(server)
All services are started normally, but on client I am getting polling-xhr.js:263 GET https://localhost:4200/socket.io/?EIO=3&transport=polling&t=MPa6ZuL net::ERR_CERT_AUTHORITY_INVALID
Why? Whats is wrong?
Browsers don't like self-signed certificates for security reasons.
To get around this in your development environment, I see three options:
Use a certificate issued by a certification unit.
It could be something free, like https://letsencrypt.org/.
Create your server dynamically, based on the development environment, not to include certificates and work directly with HTTP and WS (and not HTTPS and WSS).
Change the configuration of your browser used in development so that it accepts self-signed certificates.
For Chrome, for example, just enable the Allow invalid certificates for resources loaded from localhost. (chrome://flags/#allow-insecure-localhost) setting.
But remember that you will not be able to use self-signed certificates in production environments.

assign HTTPS to node.js socket.io

i want to create HTTPS server to my node.js socket.io server,
did it with self sign certification, using this code
var fs = require( 'fs' );
var app = require('express')();
var https = require('https');
var server = https.createServer({
key: fs.readFileSync('C:/ssl/ia.key'),
cert: fs.readFileSync('C:/ssl/ia.crt'),
requestCert: false,
rejectUnauthorized: false
},app);
server.listen(8888);
but when purchasing real one i only get .crt file, how to secure my node app using it on windows server?
Short answer: no private key - no way.
You need a private key that was used to purchase the certificate.
Or you can use letsencrypt-express:
Free SSL and managed or automatic HTTPS for node.js with Express, Koa,
Connect, Hapi, and all other middleware systems.
https://www.npmjs.com/package/letsencrypt-express
Found the answer, i had to do a CSR from my server using OPENSSL batch, in that case it will create CSR and the private KEY, buying SSL using the CSR will give me the CRT
and i will use the generated key from the OPENSSL.

Self signed cert NodeJS rejectUnauthorized

I created a structure certificates to authenticate client-> server, allowing only certificates recognized by the CA using this step by step: https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
I checked the authority with openssl, and it returns to me OK the certificate server and client, with the same CA. But by setting the parameter rejectUnauthorized to true on the server, the client can not connect.
Is there any extra parameter should I set up to allow authentication by a certificate that I generated?
---- Edit
On the client side I get the following error: ""ECONNRESET" socket hang up"
I spent a long time digging into a similar issue, and I wrote up this to talk about how to dig into various OpenSSL issues with node.js: http://www.thedreaming.org/2016/09/27/nodejs-ssl/
The short answer, though, is if you need to pass the ca parameter when creating you client connection. If you have the self-signed certificate stored in cert.pem, then the client code looks something like:
var https = require('https');
var fs = require('fs');
var certificate = fs.readFileSync('cert.pem');
var options = {
host: serverHost,
port: 443,
path: '/',
ca: [certificate]
};
https.request(options, function(res) {
res.pipe(process.stdout);
}).end();

Resources