HTTPS & Authentication
Belgian node.js User Group - 11/12/2013
Jeroen Moors
I'm a freelance consultant.
@jeroenmoors
http://jeroen.is
jeroen.moors@fluoline.net
+32 475 71 42 49


Why do we need this?

What do we need?



Identity
Ensure Bob is the real Bob

Identity
Ensure Bob is the real Bob

Identity
In a SSL world

Privacy
Encryption

Ceaser shift
Privacy
Strong encryption using PKI

Privacy
Rules of the game
- Math glues primary and public key
- Private key will ALWAYS be kept secret
- Public key can be seen by anyone
Privacy
PKI in action - Public key exchange

Privacy
PKI in action - Encrypt and decrypt

Authorization
All men are equal

What have we learned so far...
Identity
Server side: SSL Certificates
Client side: .........................
Privacy
SSL Certificates for encryption
Authorization
.........................
Certificate Initiation
Install OpenSSL
apt-get install openssl
brew install openssl
setup.exe ;)
Create a private key
# Create a directory for our certificate files
mkdir ssl
cd ssl/
# Generate a private key
openssl genrsa -out nodettps.dev.fluoline.net.key 2048
Certificate Initiation
Create a Certificate Signing Request (CSR)
openssl req -new -key nodettps.dev.fluoline.net.key \ -out nodettps.dev.fluoline.net.csr You are about to be asked to enter information... ...be left blank. ----- Country Name (2 letter code) [AU]:BE State or Province Name (full name) [Some-State]:Limburg Locality Name (eg, city) []:Hasselt Organization Name (eg, company) [Internet Widgits Pty Ltd]:Fluoline Organizational Unit Name (eg, section) []:node.js team Common Name (e.g. server FQDN or YOUR name) []:nodettps.dev.fluoline.net Email Address []:jeroen.moors@fluoline.net Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Certificate Signing
Get the certificate signed by a known CA

Certificate Signing
Choose a CA and certificate type

Certificate Signing
Compare certificates

Certificate Signing
We go cheap!

Certificate Signing
Start enrollment

Certificate Signing
Confirm order details

Certificate Signing
Copy/Paste content of the ".csr" file

Certificate Signing
Confirm Common Name (CN)

Certificate Signing
Admin details...

Certificate Signing
Choose a validator

Certificate Signing
Confirm order, initiate validation process

Certificate Signing
Confirm identity

Certificate Signing
... confirm identity

Certificate Signing
Receive the certificate!

Certificates and node.js
A basic application
// Require some modules...
var express = require('express');
var http = require('http');
// Create our express application
var app = express();
// Define some routes
app.get('/', function(req, res) {
res.send("Welcome!");
});
// Create a http for our app
var httpServer = http.createServer(app);
// Start listening
httpServer.listen(80);
basic_http.js
Add https
// Require some modules...
var express = require('express');
var path = require('path');
var fs = require('fs');
var http = require('http');
var https = require('https');
// Store the certificate details for later use
var httpsOptions = {
key: fs.readFileSync('ssl/nodettps.dev.fluoline.net.key', 'utf8'),
cert: fs.readFileSync('ssl/nodettps.dev.fluoline.net.crt', 'utf8'),
};
// Create our express application
var app = express();
// Define some routes
app.get('/', function(req, res) {
// Render
res.send("welcome");
});
// Create a http and https server for our app
var httpServer = http.createServer(app);
var httpsServer = https.createServer(httpsOptions, app);
httpServer.listen(80);
httpsServer.listen(443);
basic_https.js
TEST!
SSL Check result

Intermediate Certificates
Advisory in the certificate issuing e-mail

Download the certificates as x.509

Intermediate Certificates
Implementation in node.js
// Store the certificate details for later use
var httpsOptions = { key: fs.readFileSync('ssl/nodettps.dev.fluoline.net.key', 'utf8'), cert: fs.readFileSync('ssl/nodettps.dev.fluoline.net.crt', 'utf8'), ca: [ fs.readFileSync('ssl/geotrust_cross_root_ca.txt', 'utf8'), fs.readFileSync('ssl/rapid_ssl_ca.txt', 'utf8') ]};
basic_https_with_intermediate_certificate.js
BEAST Attack

// Store the certificate details for later use
var httpsOptions = {
key: fs.readFileSync('ssl/nodettps.dev.fluoline.net.key', 'utf8'),
cert: fs.readFileSync('ssl/nodettps.dev.fluoline.net.crt', 'utf8'),
ca: [
fs.readFileSync('ssl/geotrust_cross_root_ca.txt', 'utf8'),
fs.readFileSync('ssl/rapid_ssl_ca.txt', 'utf8')],
ciphers: 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH',
honorCipherOrder: true
};
basic_https_with_beast_mitigation.js
TLS Session resumption

var tlsSessions = require('strong-cluster-tls-store');
...
// Create a http and https server for our app
var httpServer = http.createServer(app);
var httpsServer = https.createServer(httpsOptions, app);
// Keep tlsSessions in memory
tlsSessions(httpsServer);
httpServer.listen(80);
httpsServer.listen(443);
basic_https_with_restore_session.js
Redirect http to https
// Create our express application
var app = express();
// Redirect all http traffic to https
app.use(function(req,res,next) {
if (!/https/.test(req.protocol)){
res.redirect("https://" + req.headers.host + req.url);
} else {
// If we're on https, ensure all requests will be over https
// http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
res.setHeader("Strict-Transport-Security", "max-age=31536000");
return next();
}
});
basic_https_with_http_redirect.js
What have we learned so far...
Identity
Server side: SSL Certificates (easy in node.js)
Client side: .........................
Privacy
SSL Certificates for encryption (easy in node.js)
Authorization
.........................
Identification of the client
Passport

npm install passport
- 140+ authentication strategies
- Single sign-on with OpenID and OAuth
- ...
Passport http basic example
The scenario



Passport http basic example
The code - 1/3
npm install passport
npm install passport-http
// Require Passport and its BasicStrategy module
var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
https_with_passport_basic.js
Passport http basic example
The code - 2/3
// Create our express application and configure it
var app = express();
app.configure(function() {
app.use(passport.initialize());
app.use(app.router);
});
// Initiate Passport for http Basic authentication
passport.use(new BasicStrategy(
function(username, password, done) {
if (username == "admin" && password == "demo") {
return done(null, "admin");
} else {
return done(null, false);
}
}
));
https_with_passport_basic.js
Passport http basic example
The code - 3/3
// Define some routes
// Welcome page
app.get('/', function(req, res) {
res.send("Welcome click here to login.");
});
// The protected login page
app.get('/login',
passport.authenticate('basic', { session: false }),
function(req, res) {
res.send("It is you, " + req.user + "!");
});
https_with_passport_basic.js
What have we learned so far...
Identity
Server side: SSL Certificates (easy in node.js)
Client side: Passport, multiple strategies
Privacy
SSL Certificates for encryption (easy in node.js)
Authorization
.........................
Authorization
Connect Roles

npm install connect-roles
var user = require('connect-roles');
app.use(user);
user.use('access private page', function (req) {
if (req.user.role ==== 'member') { return true; }
})
app.get('/private', user.can('access private page'), function (req, res) {
res.render('private');
});
What have we learned so far...
Identity
Server side: SSL Certificates (easy in node.js)
Client side: Passport, multiple strategies
Privacy
SSL Certificates for encryption (easy in node.js)
Authorization
Connect Roles
A "real" passport
Authentication with the Belgian eID
Prerequisites on the client side:
- A Belgian Identity card or kids-ID
- Belgian eID software:
http://eid.belgium.be/
Remark: Works best with Internet Explorer, can work with Firefox or Chrome on Linux.
Belgian eID
The scenario



Belgian eID
Extract CA certificates of the client certificate
Belgian eID
Install module and update httpsOptions
npm install client-certificate-auth
var httpsOptions = {
key: fs.readFileSync('ssl/nodettps.dev.fluoline.net.key', 'utf8'),
cert: fs.readFileSync('ssl/nodettps.dev.fluoline.net.crt', 'utf8'),
ca: [ fs.readFileSync('ssl/geotrust_cross_root_ca.txt', 'utf8'),
fs.readFileSync('ssl/rapid_ssl_ca.txt', 'utf8'),
fs.readFileSync('ssl/citizen_ca.txt', 'utf8'),
fs.readFileSync('ssl/belgium_root_ca.txt', 'utf8')
],
ciphers: 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH',
honorCipherOrder: true,
requestCert: true,
rejectUnauthorized: false
};
https_with_belgian_eid.js
Belgian eID
Modify some code...
var clientCertificateAuth = require('client-certificate-auth');
app.get('/', function(req, res) {
res.send("Welcome click here to login with your Belgian eID.");
});
app.get('/eid', clientCertificateAuth(validateCertificate), function(req, res) {
var clientCertificate = req.connection.getPeerCertificate();
var clientName = clientCertificate.subject.SN;
var clientNationalNumber = clientCertificate.subject.serialNumber;
res.send("Welcome " + clientName + " (" + clientNationalNumber + ")!");
});
function validateCertificate(cert) {
// if (cert.subject.serialNumber == in database) { return true; }
return true;
}
https_with_belgian_eid.js
Go and play!
Slides
Examples
Feedback, questions, ...
@jeroenmoors
jeroen.moors@fluoline.net
https & authentication in node.js
By Jeroen Moors
https & authentication in node.js
- 12,855