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,523