Autenticación Service

Vamos a crear un archivo de utilidades para la autenticación, estas funciones requieren de algunos módulos npm que vamos a instalar.

# Install modules
npm i -S jsonwebtoken express-jwt composable-middleware
  • jsonwebtoken : Una implementación de JSON Web Tokens.

  • express-jwt : Este módulo le permite autenticar solicitudes HTTP utilizando tokens JWT en sus aplicaciones Node.js. Los JWT se utilizan normalmente para proteger los puntos finales de la API.

  • composable-middleware: Este permite que se utilicen una serie de funciones de middleware como si fueran una única función de middleware.

Luego de esto crearemos un archivo auth/auth.service.js

auth/auth.service.js
/**
 * Auth Middleware
 */
 
const jwt = require('jsonwebtoken');
const expressJwt = require('express-jwt');
const compose = require('composable-middleware');

const User = require('../api/user/user.model');

const config = {
  secrets: {
    session: 'w0rksh0p-full5tack-j4v45cr1pt',
  },
  userRoles: ['admin', 'manager', 'user'],
};

const validateJwt = expressJwt({
  secret: config.secrets.session,
});

/**
 * Attaches the user object to the request if authenticated
 * Otherwise returns 403
 */
function isAuthenticated() {
  return compose()
    // Validate jwt
    .use((req, res, next) => {
      // allow access_token to be passed through query parameter as well
      if (req.query && req.query.hasOwnProperty('access_token')) {
        req.headers.authorization = `Bearer ${req.query.access_token}`;
      }
      // IE11 forgets to set Authorization header sometimes. Pull from cookie instead.
      if (req.query && typeof req.headers.authorization === 'undefined' && req.cookies) {
        const { token } = req.cookies;
        req.headers.authorization = `Bearer ${token}`;
      }
      validateJwt(req, res, next);
    })
    // Attach user to request
    .use((req, res, next) => {
      User.findById(req.user._id).exec()
        .then((user) => {
          if (!user) {
            return res.status(401).end();
          }
          req.user = user;
          next();
          return null;
        })
        .catch(err => next(err));
    });
}

/**
* Checks if the user role meets the minimum requirements of the route
*/
function hasRole(roleRequired) {
  if (!roleRequired) {
    throw new Error('Required role needs to be set');
  }

  return compose()
    .use(isAuthenticated())
    .use((req, res, next) => {
      if (config.userRoles.indexOf(req.user.role) >= config.userRoles.indexOf(roleRequired)) {
        return next();
      }
      return res.status(403).send('Forbidden');
    });
}

/**
* Returns a jwt token signed by the app secret
*/
function signToken(id, role) {
  return jwt.sign({ _id: id, role }, config.secrets.session, {
    expiresIn: 60 * 60 * 5,
  });
}

module.exports = {
  isAuthenticated,
  hasRole,
  signToken,
};

Básicamente este archivo tendrá las funciones/middleware de cómo saber si un usuario esta logueado, si el rol del usuario que esta solicitando un recurso puede acceder a el, la codificación y decodificación del token.

Finalmente vamos a crear el archivo index.js que será el encargado de tener todas las diferentes estrategias de autenticación de nuestra plataforma, como Facebook, Google entre otras. Este archivo en sí tendrá finalmente rutas de express con la lógica necesaria para la autenticación.

auth/index.js
/**
 * Auth configuration
 * @author: Cristian Moreno Zulauaga <khriztianmoreno@gmail.com>
 */

const express = require('express');

const User = require('../api/user/user.model');
const authLocal = require('./local/passport');
const configPassportLocal = require('./local');

// Passport Configuration
authLocal.setup(User);

const router = express.Router();

router.use('/local', configPassportLocal);

module.exports = router;

En el siguiente punto vamos a configurar Passport.js para usarlo dentro de Express.js y como agregar alguno de los middlewares que creamos acá a un endpoint.

Last updated