/** * @fileOverview Security handler functions for the integrations API */ 'use strict'; const debug = require('debug')('integration-api:security'); const config = require(global.configFile); const utils = require(global.pathPrefix + 'utils.js'); const tokenUtils = require(global.pathPrefix + '../utils/tokens.js'); const hashingUtils = require(global.pathPrefix + '../utils/hashing.js'); module.exports = { bearer: bearer }; /** * Handler for the `bearer` security type. It checks the bearer token is valid, * and if so it fills in a `req.session` object with relevant session information. * * * @param {Object} req - the express request * @param {Object} def - the swagger security definition * @param {string} scopes - the value of the Authorization header * @param {function(error, v)} callback - Result callback */ function bearer(req, def, scopes, callback) { debug('bridgeSession credentials verification'); // // Check that there exists at least some value for X-XSRF-TOKEN // if (!scopes || scopes.indexOf('Bearer ') !== 0) { debug('- no credentials supplied'); reportError(callback); return; } // // Validate the token // const token = scopes.substr(7); // Remove the `Bearer ` from the front const tokenP = tokenUtils.validateToken(token).then( function onSuccess(result) { // // Make a pseudo-session token out of our token. We do this // by hashing the token, with the Client's _id as salt, then cropping // the result to our token length. We crop from the end of the string // to avoid the :: at the start // let hashP = hashingUtils.regenerateHash( +config.passwordCryptoVersion, result.decoded.token, result.client._id.toString() ).then((hash) => hash.slice(-1 * utils.tokenLength)); // // Store the Merchant's client in the session for the controllers to // access. // hashP.then((hash) => { req.session = { data: { PseudoSession: hash, Merchant: result.client } }; callback(); }).catch((err) => { // // Some error in generating the hash. Just use the default error // reportError(callback); }); }, function onError(error) { // // Don't differentiate sources of error for security reasons // reportError(callback); } ); } // // Function to return a consistent error response for failures to authenticate. // This function is deliberately light on details so as not to leak extra // information. // // @param {securityCallback} callback - The callback to use for responses // function reportError(callback) { var error = new Error('Not authorised'); error.statusCode = 401; return callback(error); }