Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I will post both of the modules, some of the code in them may be "irrelevant" for the main concern here, which is Security.prototype.authenticate(). Nevertheless, comments are welcome about all of the code.

Security.prototype.authenticate() is a controller for a /login API-endpoint.

security.js

'use strict';

var crypto = require('crypto');
var jwt = require('jsonwebtoken');
var Promise = require('bluebird');

var config = require('./config');
var db = require('./db');

function Security() {}

function _verifyPassword(password, hash, salt) {
    var newHash = crypto.createHash('sha512').update(password).update(salt).digest("hex");
    return newHash === hash;
}

function _generateToken(username, secret, expiration) {
    var token = jwt.sign(username, secret, { expiresInMinutes: expiration });
    return { token: token };
}

Security.prototype = {

    tokenCheck: function(req, res) {

        jwt.verify(req.body.token, config.security.secret, function (err, decoded) {

            if (err) {
                return res.status(400).send("Token invalid or expired");
            }

            res.json({ username: decoded });

        });

    },

    authenticate: function(req, res) {

        if (!req.body.username || !req.body.password) {
            return res.status(400).send("Username and/or password field empty");
        }

        Promise.using(db.getConnection(), function(connection) {

            return connection.queryAsync("SELECT password_hash, password_salt FROM users WHERE email = ? AND admin = 1", req.body.username)
                .then(function(rows) {

                    connection.release();

                    if ( rows[0].length === 1 ) {
                        return rows[0][0];
                    } else {
                        throw new Error("Username not found");
                    }

            }).then(function(user) {

                    if ( !_verifyPassword(req.body.password, user.password_hash, user.password_salt) ) {
                        throw new Error("Incorrect password");
                    }

                    res.json({
                        token: _generateToken(req.body.username, config.security.secret, config.security.expiration),
                        username: req.body.username
                    });

            });

        }).error(function(e) {
            res.status(400).send("Database error");
        }).catch(Error, function(e) {
            res.status(400).send(e.message);
        });

    }

};

module.exports = new Security();

db.js

'use strict';

var config = require('./config');
var Promise = require("bluebird");
var mysql = require('mysql');
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);

function DB() {
    this._pool = _createPool();
}

function _createPool() {

    return mysql.createPool({
        connectionLimit: config.database.connectionLimit,
        host: config.database.host,
        user: config.database.username,
        password: config.database.password,
        database: config.database.database,
        debug: config.database.debug
    });

}

DB.prototype = {

    getConnection: function() {
        return this._pool.getConnectionAsync();
    }

};

module.exports = new DB();

My concerns are any possible anti-patterns that are visible here. I just got rid of one problem with this function, which was nested callbacks, by implementing promises. However, my knowledge of Bluebird is limited to the last ~12 hours. I have used promises before, but not a lot. Also, as I said, comments on the rest of the code are also welcome.

share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.