Source: auth.service.js

/**
 *  @fileOverview A service that handles login and authentication on each request.
 *
 *  @author       Ralfs Lagzda
 *
 *  @requires     NPM:mongoose
 *  @requires     NPM:jsonwebtoken
 *  @requires     ../models/user
 *  @requires     ../config
 */
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');

mongoose.Promise = global.Promise;
const User = require('../models/user');
const config = require('../config');

/**
 * Authenticates a user based on the signed JWT token
 *
 * @memberOf AuthService
 * @function authenticate
 * @param {String} token - The signed user JWT token string
 * @returns {Promise<User>} Promise that eventually authenticates
 * and resolves the user or fails
 */
const authenticate = token => new Promise(async (resolve, reject) => {
  if (token) {
    jwt.verify(token, config.secretKey, (err, decode) => {
      if (err) reject(Error({ message: 'Invalid token' }));
      else resolve(decode.user);
    });
  } else {
    reject(Error({ message: 'No token' }));
  }
});

/**
 * Login a user based on the credentials
 *
 * @memberOf AuthService
 * @function login
 * @param {Object} credentials - The user credential object containing username and password
 * @param {string} credentials.username - The username.
 * @param {string} credentials.password - The password.
 * @returns {Promise<User>} Promise that eventually authenticates
 * and resolves the user with JWT or fails
 */
const login = credentials => new Promise(async (resolve, reject) => {
  try {
    const user = await User.findOne({ username: credentials.username });
    if (!await user.verifyPassword(credentials.password)) throw (Error('Invalid login'));
    user.password = undefined;
    const token = jwt.sign({
      expiresIn: 60 * 60 * 60 * 3, // expires in 3 hours
      user,
    }, config.secretKey);
    resolve({ token, user });
  } catch (err) {
    reject(err);
  }
});

/**
 * Authorizes access to a user or resource owned by a user
 *
 * @memberOf AuthService
 * @function authorize
 * @param {Object} authenticatedUser - The user which is currently authenticated
 * @param {string} authenticatedUser.id - The id of the user.
 * @param {String} userId - The user id in the path to access a resource
 * @returns {Promise<Boolean>} Promise that eventually authorizes the user
 * and resolves a boolean or fails
 */
const authorize = (authenticatedUser, userId) => new Promise((resolve, reject) => {
  if (authenticatedUser.id === userId) resolve();
  else reject(Error({ message: 'Not authorized' }));
});
/**
 * A service that handles login and authentication on each request
 * @namespace AuthService
 */
module.exports = {
  authenticate,
  authorize,
  login,
};