v0.0.8 Security and logout - zhentian-wan/MEANAppsFiles GitHub Wiki
We need to crypt the user password CANNOT leave it as text.
**Install: **
npm install crypto --save
Crypt the password
We pass password and a random salt to a hash algorithm, then it will generate the Hashed password. This hashed password cannot be reversed to the text password. So it has a high security.
config/mongoose.js
crypto = require('crypto');
//Users data
var userSchema = mongoose.Schema({
firstName: String,
lastName: String,
username: String,
salt: String,
hash_pwd: String
});
//Add a method to the userSchema, which authenticate the user.
userSchema.methods = {
authenticate: function(passwordToMatch){
return hashPwd(this.salt, passwordToMatch) === this.hash_pwd;
}
};
We need to update the user schema, add salt and hash_pwd.
We also need methods to generate salt and hash_pwd
function createSalt(){
return crypto.randomBytes(128).toString('base64');
}
function hashPwd(salt, pwd){
var hmac = crypto.createHmac('sha1', salt);
return hmac.update(pwd).digest('hex');
}
Test Data
User.find({}).exec(function(err, collection){
if(_.size(collection) === 0){
var salt, hash;
salt = createSalt();
hash = hashPwd(salt, 'John');
User.create({firstName: 'John', lastName: 'Linquist', username: 'John', salt: salt, hash_pwd: hash});
salt = createSalt();
hash = hashPwd(salt, 'Ken');
User.create({firstName: 'Ken', lastName: 'CD', username: 'Ken', salt: salt, hash_pwd: hash});
salt = createSalt();
hash = hashPwd(salt, 'Ben');
User.create({firstName: 'Ben', lastName: 'Cophen', username: 'Ben', salt: salt, hash_pwd: hash});
}
})
We just use username as password to create test data.
config/passport.js So when we authenticate the user, not only check the username exists or not, we also check the password.
passport.use(new LocalStrategy(
function(username, password, done){
User.findOne({username: username}).exec(function(err, user){
if(user && user.authenticate(password)){
return done(null, user);
}else{
return done(null, false);
}
});
}
));
Once page refreshed, client side need to login again problem
To fix this problem, first we need to know that once the user has logged in, the server side know the logged in user. Even user refresh the page. But client side doesn't know, because we didn't save the information.
So on the server side, when we send back index page, we also send back the current user if any. And on the client side once user logged in, we save the user information in $window. so when the page refreshed, if the $window info exists, we show the logged in status.
server side
config/routes.js
// All routes handled by this route, give client side to handle
app.get('*', function(req,res) {
res.render('index', {
bootstrappedUser: req.user //server will remember the current user
});
});
client side
layout.jade Include a new file called currentUser
doctype
html
head
title Multivision
link(href="/favicon.ico", rel="shortcut icon", type="image/x-icon")
link(href="/css/bootstrap.css", rel="stylesheet")
link(href="/vendor/toastr/toastr.min.css" rel='stylesheet')
link(href="/css/site.css", rel="stylesheet")
body(ng-app="app")
include currentUser
block main-content
//include all the javascript files
include scripts
currentUser.jade: Add bootstrappedUser to the window object using json format
if !!bootstrappedUser
script
window.bootstrappedUserObject = !{JSON.stringify(bootstrappedUser)}
identiy.js
Check whether bootstrappedUserObject exists.
function IdentityFactory($window) {
var factory = {},
currentUser;
if($window.bootstrappedUserObject ){
currentUser = $window.bootstrappedUserObject;
}
factory.currentUser = currentUser;
factory.isAuthed = function() {
return !!factory.currentUser;
};
return factory;
}
angular.module('app')
.factory('IdentityFactory', IdentityFactory);