TodoList Con Node.js Y MongoDB - Parte II

2 minuto de lectura

Lo prometido es deuda, aquí vamos con la segunda parte donde integraremos Passport para poder validar los request y contronlar sesiones de usuarios.

Primero debemos agregar los siguientes imports al archivo app.js y la estrategia (plugin de autenticación) a utilizar. Además se agregan los archivos UserModel.js y security.js extensión del modelo de User y métodos de validación del request respectivamente:

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var security = require('./config/security');
var User = require('./model/UserModel');

Ahora configuramos Express para que pueda utilizar Passport como administrador de sesiones de usuario. Es necesario que express use su propio administrador de sesiones y además debe ser inicializado antes que el de passport.

app.use(express.cookieParser('your secret here'));
app.use(express.session());

// passport initialize
app.use(passport.initialize());
app.use(passport.session());

Luego agregamos mecanismos de autenticación, serialización y deserialización a passport:

passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

Model

Ahora extendemos el modelo de usuario para agregar nuestros atributos (si es es necesario, por ahora lo dejaremos vacío):

var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');

var UserSchema = new mongoose.Schema({});

UserSchema.plugin(passportLocalMongoose);

var UserModel = mongoose.model('User', UserSchema);

module.exports = UserModel;

Seguridad

Hay un archivo que se llama security.js que contiene una función que valida si el request solicitado está autenticado por passport, si está autenticado lo “deja pasar” (next), de lo contrario lo redirecciona al template de login.

exports.ensureAuthenticated = function ensureAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return next();
    }
    res.redirect('/login');
};

Nos queda asegurar las urls o recursos que necesitemos con la función ensureAuthenticated en el archivo app.js. La idea es que sea lo menos intrusivo posible. Hay dos formas de hacerlo, la primera es intrusiva (y no recomendada aunque puede utilizarse con fines específicos) y se debe realizar por cada request en los archivos que contienen los Controllers:

exports.authenticationExample = function(req, res) {
    if (req.isAuthenticated()) {
        // Do something
    } else {
        res.redirect('/login');
    }
}

La segunda es interceptando los request y validando según algún patrón, que es nuestro caso. Esta configuración esta en app.js donde se declaran las rutas a los Controllers:

app.all('/api/*', security.ensureAuthenticated);
app.all('/todos', security.ensureAuthenticated);

Con esto interceptamos todos los request que van a la API y los que van a /todos y los hacemos pasar por la función de autenticación de request. Con esto evitamos poner dichas líneas de autenticación en cada controller.

Login y Logout

Finalmente nos queda la última parte respecto de la autenticación y es configurar el login y el logout. Para el login usamos la API de passport y delegamos el trabajo de autenticación de la siguiente forma (configuración):

/**
 * Funcion sin autenticación que permite desplegar el template de Login
 */
app.get('/login', function(req, res) {
    res.render('login', {});
});

/**
 * Función de login que permite delegar la autenticacion en la API de
 *  passport, se configura además cuando la autenticación es exitosa a que url 
 *  lo debe redireccinar y lo mismo en caso de error.
 */
app.post('/login', passport.authenticate('local', {
    successRedirect: '/todos',
    failureRedirect: '/login'
}));

El logout es más sencillo y lo único que hay que hacer es invalidar el request, destruir la sesión del usuario y redireccionar al login.

app.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/login');
});

Me queda pendiente en la próxima parte del tutorial explicar cómo consumir estos servicios usando angular y desplegar los templates.

Comentar