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 filesmkdir sslcd ssl/
# Generate a private keyopenssl 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:

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