Home

Awesome

nodejs-ssl-trusted-peer-example

This is a working example of a trusted-peer setup using HTTPS / SSL.

This is a kind of "part 2" to coolaj86/nodejs-self-signed-certificate-example.

See also:

Test for yourself

An example that works.

example
├── make-root-ca-and-certificates.sh
├── package.json
├── serve.js
├── request.sh
└── request.js

Get the repo

git clone git@github.com:coolaj86/nodejs-ssl-trusted-peer-example.git
pushd nodejs-ssl-trusted-peer-example
npm install

For the super impatient:

bash test.sh

This will

Create certificates for your FQDN

local.foobar3000.com points to localhost, so it's ideal for your first test.

bash make-root-ca-and-certificates.sh local.foobar3000.com 8043

This will ask you to create a passphrase to protect your p12 file. If you forget the passphrase, the file can easily be recreated later (see source in the file).

For the purposes of this tutorial, I recommend choosing 'secret'

certs/
├── ca
│   ├── my-root-ca.crt.pem
│   ├── my-root-ca.key.pem
│   └── my-root-ca.srl
├── client
│   ├── my-app-client.crt.pem
│   ├── my-app-client.key.pem
│   ├── my-app-client.p12
│   └── my-root-ca.crt.pem
├── server
│   ├── my-root-ca.crt.pem
│   ├── my-server.crt.pem
│   └── my-server.key.pem
└── tmp
    ├── my-app-client.csr.pem
    └── my-server.csr.pem

Run the server

node ./serve.js 8043 &
# use `fg` and `ctrl+c` to kill

Test in a client

Test in node.js

node ./request.js local.foobar3000.com 8043

Test with cURL

curl -v -s "https://local.foobar3000.com:8043" \
  --key certs/client/my-app-client.key.pem \
  --cert certs/client/my-app-client.crt.pem \
  --cacert certs/client/my-root-ca.crt.pem

Visit in a web browser

https://local.foobar3000.com:8043

To get rid of the browser errors and warnings, simply add the certificate from the client folder to your list of certificates by alt-clicking "Open With => Keychain Access" on my-root-ca.crt.pem and also on my-app-client.p12 (you will need to use the passphrase you created earlier)

You do have to set Always Trust a few times as explained by Rob Peck.

Now season to taste

You can poke around in the files for generating the certificates, but all you really have to do is replace local.foobar3000.com with your very own domain name.

Show me the Magic!

You have 3 different certificates with private / public pairs:

Since the server's CA list is overwritten with only the self-signed Root CA only clients which have a certificate signed by that CA will be trusted (or potentially something else in the same certificate chain).

On the server

https.createServer({
  key: fs.readFileSync(path.join(__dirname, 'certs', 'server', 'my-server.key.pem'))
, ca: [ fs.readFileSync(path.join(__dirname, 'certs', 'server', 'my-root-ca.crt.pem'))]
, cert: fs.readFileSync(path.join(__dirname, 'certs', 'server', 'my-server.crt.pem'))
, requestCert: true
, rejectUnauthorized: true
})

If you need to selectively trust certain servers and clients when serving and making requests, or also serve to public clients you may need to have multiple servers and clients. ssl-root-cas will probably help.

In the client

var options
  ;

options = {
  host: 'local.foobar3000.com'
, port: 8043
, path: '/'
, ca: [ fs.readFileSync(path.join(__dirname, 'certs', 'client', 'my-root-ca.crt.pem')) ]
, key: fs.readFileSync(path.join(__dirname, 'certs', 'client', 'my-app-client.key.pem'))
, cert: fs.readFileSync(path.join(__dirname, 'certs', 'client', 'my-app-client.crt.pem'))
};
options.agent = new https.Agent(options);

https.request(options, handler);

The node example for this (http://nodejs.org/api/https.html) is a bit confusing. I'll have to read the source to better understand why the options are laid out as such.

What About WebSockets?

Viola: https://groups.google.com/forum/#!topic/nodejs/KJPk8aibQHY

Other SSL Resources

Zero-Config clone 'n' run (tm) Repos:

Articles