Tuesday, October 21, 2014

NODEJS - Basic Access Authentication

Previous Post


This article is about how to do basic authentication with NodeJS.

Checkout my project on GitHub. For one who never checkout my project before.

vanduc@VGN-FZ290E:~/test2$ git clone --depth=10 https://github.com/vanduc1102/nodejs-example.git
vanduc@VGN-FZ290E:~/test2$ cd nodejs-example/
vanduc@VGN-FZ290E:~/test2/nodejs-example$ git checkout -f 3-basic-auth
vanduc@VGN-FZ290E:~/test2/nodejs-example$ npm install
vanduc@VGN-FZ290E:~/test2/nodejs-example$ node index.js

For one who already checked out my project.

vanduc@VGN-FZ290E:~/test2/nodejs-example$ git pull
vanduc@VGN-FZ290E:~/test2/nodejs-example$ git checkout -f 3-basic-auth
vanduc@VGN-FZ290E:~/test2/nodejs-example$ npm install
vanduc@VGN-FZ290E:~/test2/nodejs-example$ node index.js

You can login with username and password is  admin:123456

The code require authentication on server side:


var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var app = express();
app.use(bodyParser.json());
app.use(cookieParser());
app.use(session({
 secret: '1234567890QWERTY',
    saveUninitialized: true,
    resave: true}));
var realm = 'localhost';
function unauthorized(res, realm) {
    res.statusCode = 401;
    res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
    res.setHeader('Content-Type', 'text/html');
    res.end("This request requires HTTP authentication");
}
function checkLogin(username, password, callback){
 if(username =='admin' && password =='123456')
 {
  callback(null,username);
 }
 else
 {
  callback('worng user name',username);
 }
};
app.use(function (req, res, next) {
    var authorization = req.headers.authorization;
    var session = req.session;
    if (req.user) {
        console.log('User already stored in request : ' + req.user);
        return next();
    }

    if (!authorization) {
        return unauthorized(res, realm);
    }
    var parts = authorization.split(' ');
    if (parts.length !== 2) return next(error(400));
    var scheme = parts[0]
        , credentials = new Buffer(parts[1], 'base64').toString()
        , index = credentials.indexOf(':');
    if ('Basic' != scheme || index < 0)
    {
     return next(error(400));
    }
    var user = credentials.slice(0, index)
        , pass = credentials.slice(index + 1);
 if(session.user_id != ''&&session.user_id == user){
        return next();
    }
    //async check authentication
    checkLogin(user, pass, function (err, username) {
        if (err != null) {
            session.destroy();
            req.user = req.remoteUser = null;
            return unauthorized(res, realm);
        }
        req.user = req.remoteUser = user;
        session.user_id = user;
        next();
    })
});

Then we use the tricky code for doing the logout basic authentication:

$(document).ready(function(){
      $('span.logout').on('click',function(e){
           e.preventDefault();
                var xmlHttp;
                if (window.XMLHttpRequest) {
                    xmlHttp = new XMLHttpRequest();
                }
                // code for IE
                else if (window.ActiveXObject) {
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                }
                if (window.ActiveXObject) {
                    // IE clear HTTP Authentication
                    document.execCommand("ClearAuthenticationCache");
                    window.location.reload();
                } else {
                    xmlHttp.open("GET", window.location, true, "logout", "logout");
                    xmlHttp.send("");
                    xmlHttp.onreadystatechange = function () {
                        if (xmlHttp.readyState == 4) {
                            window.location.reload();
                        }
                    }
                }
                return false;
      });
    });

In order to secured your site with basic access authentication, You must provide SSL connection.
Otherwise it is not good solution.
Some disvantages of basic-auth is you cant modify the login pop-up, It depends on the browser provider.
The user credentials will store on browers cache .... :( very bad


Next Post