From 03b55c108750117206d0178363a3dedf6e1521dc Mon Sep 17 00:00:00 2001 From: Dennis Eriksen Date: Wed, 24 Apr 2013 02:27:58 +0200 Subject: made login work with passport --- router.js | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- views/login.ejs | 8 +-- 2 files changed, 169 insertions(+), 7 deletions(-) diff --git a/router.js b/router.js index c63d293..4130ee7 100644 --- a/router.js +++ b/router.js @@ -1,8 +1,154 @@ -var passlo = require('./modules/passport-local') - , passport = require('passport') - , EM = require('./modules/email-dispatcher'); +var passport = require('passport') + , LocalStrategy = require('passport-local').Strategy + , mongodb = require('mongodb') + , mongoose = require('mongoose') + , bcrypt = require('bcrypt') + , SALT_WORK_FACTOR = 15; + + +// connects to mongodb +mongoose.connect('localhost', 'test'); +var db = mongoose.connection; +db.on('error', console.error.bind(console, 'connection error:')); +db.once('open', function callback(){ + console.log('Connected to MongoDB'); +}); + +// user scheme +var userSchema = mongoose.Schema({ + username: { type: String, required: true, unique: true }, + email: { type: String, required: true, unique: true }, + password: { type: String, required: true }, //passwords doesn't need to be unique + accessToken:{ type: String } // used for Remember Me +}); + +// bcrypt middleware +userSchema.pre('save', function(next) { + var user = this; + + if (!user.isModified('password')) return next(); + + bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) { + if(err) return next(err); + + bcrypt.hash(user.password, salt, function(err, hash) { + user.password = hash; + next(); + }); + }); +}); +// password verification +userSchema.methods.comparePassword = function(candidatePassword, cb) { + bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { + if (err) return cb(err); + cb(null, isMatch); + }); +}; +// remember me implementation +userSchema.methods.generateRandomToken = function () { + var user = this, + chars = "_!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", + token = new Date().getTime() + '_'; + for (var x = 0; x < SALT_WORK_FACTOR; x++) { + var i = Math.floor(Math.random() * 94); + token += chars.charAt(i); + } + return token; +}; + +// seed a test user +var User = mongoose.model('User', userSchema); + +var usr = new User({ username: 'bob', email: 'bob@example.com', password: 'secret' }); +usr.save(function(err) { + if (err) { + console.log(err); + } else { + console.log('user: ' + usr.username + + 'saved.'); + } +}) + +// Passport session setup. +// To support persistent login sessions, Passport needs to be able to +// serialize users into and deserialize users out of the session. Typically, +// this will be as simple as storing the user ID when serializing, and finding +// the user by ID when deserializing. +// +// Both serializer and deserializer edited for Remember Me functionality +passport.serializeUser( function(user, done) { + var createAccessToken = function() { + var token = user.generateRandomToken(); + User.findOne( { accessToken: token }, function (err, existingUser) { + if (err) return done(err); + if (existingUser) { + createAccessToken(); //run it again. has to be unique + } else { + user.set('accessToken', token); + user.save( function(err) { + if (err) return done(err); + return done(null, user.get('accessToken')); + }); + } + }); + } + if (user._id) { createAccessToken(); } +}); + +passport.deserializeUser( function(token, done) { + User.findOne( { accessToken: token }, function(err, user) { + done(err, user); + }); +}); + +// Use the LocalStrategy within Passport. +// Strategies in passport require a `verify` function, which accept +// credentials (in this case, a username and password), and invoke a callback +// with a user object. In the real world, this would query a database; +// however, in this example we are using a baked-in set of users. +/*passport.use(new LocalStrategy(function(username, password, done) { + User.findOne({ username: username }, function(err, user) { + if (err) return done(err); + if (!user) { return done(null, false, { message: 'Unknown user ' + username }); } + user.comparePassword(password, function(err, isMatch) { + if (err) return done(err); + if (isMatch) { + return done(null, user); + } else { + return done(null, false, { message: 'Invalid password' }); + } + }); + }); +}));*/ + +passport.use(new LocalStrategy(function(username, password, done) { + User.findOne({ username: username }, function(err, user) { + if (err) { return done(err); } + if (!user) { return done(null, false, { message: 'Unknown user ' + username }); } + user.comparePassword(password, function(err, isMatch) { + if (err) return done(err); + if(isMatch) { + return done(null, user); + } else { + return done(null, false, { message: 'Invalid password' }); + } + }); + }); +})); + + +// to ensure that users are logged in +function ensureAuthenticated(req, res, next) { + if (req.isAuthenticated()) return next(); + res.redirect('/login'); +} + +/* + * ============================================================ + * Routes + * + */ @@ -45,6 +191,7 @@ module.exports = function(app) { */ app.get('/dashboard', function(req, res) { + ensureAuthenticated(); res.render('dashboard', { title: 'kanin', loggedin: true @@ -81,6 +228,21 @@ module.exports = function(app) { })(req, res, next); }); + + + /* + * GET logout + * + * '/logout' + */ + app.post('/logout', function(req, res) { + req.logout(); + res.redirect('/'); + }); + + + + /* * GET project page * diff --git a/views/login.ejs b/views/login.ejs index c0c542d..e3f6e57 100644 --- a/views/login.ejs +++ b/views/login.ejs @@ -7,9 +7,9 @@

Hello!

Please Login To Your Account

- + - +