Lab 19: Autentificación

Descripción

En esta actividad exploraremos el proceso de autentificación de usuarios.

Modalidad

Individual.

Objetivos de aprendizaje
  • Entender cómo funciona la autentificación de usuarios.
  • Desarrollar aplicaciones web con autentificación de usuarios.
  • Desarrollar aplicaciones web con rutas protegidas.
  • Desarrollar aplicaciones web protegidas contra ataques CSRF.
Instrucciones
  • Revisa junto con el profesor la presentación sobre Autentificación
  • Crea la funcionalidad para registrar nuevos usuarios. Recuerda validar que el usuario no exista. Es importante que cuando se guarda un password, lo encriptemos con un método no desencriptable, para que si alguien tiene acceso a la base de datos, no pueda descifrar el password. Un paquete que nos puede servir para ello es bcryptjs, por lo que hay que instalarlo con npm install --save bcryptjs.
    Para encriptar los passwords:
    //En un modelo
    const bcrypt = require('bcryptjs');
    
    //Dentro del método del modelo que crea el usuario
    //El segundo argumento es el número de veces que se aplica el algoritmo, actualmente 12 se considera un valor seguro
    //El código es asíncrono, por lo que hay que regresar la promesa
    return bcrypt.hash(password, 12); 
                            
  • Crea la funcionalidad para que un usuario se autentifique. Para ello deberás realizar una consulta a la base de datos recuperando el usuario (si es que existe)y posteriormente, comparar el password introducido por el usuario con el password encriptado en la base de datos. Esto se puede lograr en el controlador de la siguiente forma:
    bcrypt.compare(request.body.password, user.password)
        .then(doMatch => {
            if (doMatch) {
                request.session.isLoggedIn = true;
                request.session.user = user;
                return request.session.save(err => {
                    response.redirect('/');
                });
            }
            response.redirect('/login');
        }).catch(err => {
            response.redirect('/login');
        });
    
                            
  • Para mejorar la seguridad de nuestro sitio, es importante proteger las rutas. En el código anterior definimos una variables de sesión (isLoggedIn) para indicar que el usuario está autentificado. Esta variable nos puede ayudar en los controladores para proteger una ruta en particular:
    exports.ruta = (request, response, next) => {
        if (!request.session.isLoggedIn) {
            return response.redirect('/login');
        }
        //Resto del código de la ruta...
    }
                            
    Una alternativa más elegante y sin repetición de código, es implementando la protección en un middleware. Esto lo podemos hacer en un nuevo archivo, por ejemplo, is-auth.js:
    module.exports = (request, response, next) => {
        if (!request.session.isLoggedIn) {
            return response.redirect('/login');
        }
        next();
    }
                            
    Para usar nuestro middleware, basta con ir a cualquier archivo de rutas o nuestro archivo principal y agregar:
    const isAuth = require('./is-auth.js');
    
    router.get('/miRuta', isAuth, miControlador.miAccion);
                            
  • Nuestro trabajo hasta ahora, ha sido suficientemente bueno para usuarios de confianza. Sin embargo, la web no es un lugar seguro. Por ello es importante preparar nuestras aplicaciones para protegernos contra usuarios malintencionados. Un ataque común es el Cross-Site Request Forgery (CSRF), el cual implica aprovecharse de una sesión de otro usuario, comúnmente perpretado desde una página que parece la oficial pero que en realidad no lo es.
    Para evitar ataques de CSRF, tenemos que asegurar que nuestros usuarios estén trabajando sobre las vistas que nosotros proveemos. Esto lo podemos lograr por medio de un Token CSRF en nuestras formas y con ayuda de la instalación del paquete csurf.
    Para usar el paquete en nuestra aplicación: 1) tenemos que configurar el middleware, lo cual automaticamente protegerá todas nuestras peticiones POST:
    const csrf = require('csurf');
    const csrfProtection = csrf();
    
    //...Y después del código para inicializar la sesión... 
    app.use(csrfProtection); 
                            
    Al proteger las peticiones POST, nuestra aplicación deja parcialmente de funcionar porque no estamos mandando el token CSRF desde nuestras formas, por ello tenemos que 2) Mandarle el token a las vistas desde el controlador:
    exports.getAccion = (request, response, next) => {
        response.render('/ruta', {
            csrfToken: request.csrfToken()
        });
    }
                            
    Y 3) tenemos que desplegarlo en la vista:
    
    <form action="ruta" method="POST">
    <input type="hidden" name="_csrf" value="<%= csrfToken %>" >
                            
  • Una alternativa elegante al paso 2) del apartado anterior, es utilizando Middleware y variables locales de las vistas:
    app.use((request, response, next) => {
        response.locals.csrfToken = request.csrfToken();
        next();
    });
                            
  • Continúa mejorando tus laboratorios anteriores o tu proyecto, esta vez agregándoles autentificación de usuarios, protección de rutas y protección contra ataques CSRF. Recuerda que siempre tienes también la opción de crear una nueva aplicación.
Preguntas a responder
  • ¿Qué otras formas de autentificación existen?
Recursos
Especificaciones de entrega

A través de tu repositorio personal (Bitbucket o GitHub).