Simple login page in nodejs using express and passport with mongodb
Here is a simple setup using passport to login / logout the users:
On the main app.js file
/* Auth config --------------------------------*/// @see http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/var passport = require('passport');var User = require('./app/models/User'),passport.use(User.localStrategy);passport.serializeUser(User.serializeUser);passport.deserializeUser(User.deserializeUser);// Default session handling. Won't explain it as there are a lot of resources out thereapp.use(express.session({ secret: "mylittlesecret", cookie: {maxAge: new Date(Date.now() + 3600000)}, // 1 hour maxAge: new Date(Date.now() + 3600000), // 1 hour store: new RedisStore(config.database.redis), // You can not use Redis }));// The important part. Must go AFTER the express session is initializedapp.use(passport.initialize());app.use(passport.session());// Set up your express routesvar auth = require('./app/controllers/authController.js');app.post('/auth/login', auth.login);app.post('/auth/logout', auth.logout);app.get('/auth/login/success', auth.loginSuccess);app.get('/auth/login/failure', auth.loginFailure);
On your user model (ej. app/models/User.js)
I'm using the passport-local module, which further simplifies the login logic:https://github.com/jaredhanson/passport-local
/* Your normal user model ----------------------*/var mongoose = require('mongoose'), ObjectId = mongoose.Schema.Types.ObjectId, PassportLocalStrategy = require('passport-local').Strategy;var schema = new mongoose.Schema({ name: {type:String, required:true, trim:true}, email: {type:String, required: true, trim: true, lowercase:true, unique: true}, image: {type:String}, password: {type:String, required: true }, created: {type: Date, default: Date.now}});/* Auth properties ---------------------------*//* (passport) ---------------------------*/// This is your main login logicschema.statics.localStrategy = new PassportLocalStrategy({ usernameField: 'email', passwordField: 'password', }, // @see https://github.com/jaredhanson/passport-local function (username, password, done){ var User = require('./User'); User.findOne({email: username}, function(err, user){ if (err) { return done(err); } if (!user){ return done(null, false, { message: 'User not found.'} ); } if (!user.validPassword(password)){ return done(null, false, { message: 'Incorrect password.'} ); } // I'm specifying the fields that I want to save into the user's session // *I don't want to save the password in the session return done(null, { id: user._id, name: user.name, image: user.image, email: user.email, }); }); });schema.methods.validPassword = function(password){ if (this.password == password){ return true; } return false;}schema.statics.serializeUser = function(user, done){ done(null, user);};schema.statics.deserializeUser = function(obj, done){ done(null, obj);};var model = mongoose.model('User', schema);exports = module.exports = model;
On app/controllers/authController.js
I'm using a single-page application, so I'm returning JSON on login / logout. If you wish to redirect to somewhere else, you will have to modify the "login success" and "login failure" functions (or call res.render(...) or whatever).
var passport = require('passport');var AuthController = { // Login a user login: passport.authenticate('local', { successRedirect: '/auth/login/success', failureRedirect: '/auth/login/failure' }), // on Login Success callback loginSuccess: function(req, res){ res.json({ success: true, user: req.session.passport.user }); }, // on Login Failure callback loginFailure: function(req, res){ res.json({ success:false, message: 'Invalid username or password.' }); }, // Log out a user logout: function(req, res){ req.logout(); res.end(); },};exports = module.exports = AuthController;
Lastly, you should point your login form (which needs to have the method="post"
attribute set) to /auth/login. On login success, the "loginSuccess" callback will be executed. On login failure, the "loginFailure" callback will be executed.
Edit:
You can create new users in your mongo database by executing something like:
// On your main app.js fileapp.post('/auth/register', auth.register);// On your authController.js file, as per the previous examplevar User = require('./app/models/User'); // The model we defined in the previous example ...register: function(req, res){ User.create({name: req.body.name, email: req.body.email, password: req.body.password}, function(err){ if (err) { console.log(err); ... // Your register error logic here res.redirect('/* Your error redirection path */'); return; } res.redirect('/* Your success redirection path */'); });},...
Then, point a registration form to /auth/register. I didn't validated the data, but you should validate it before trying to save the user.