95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
/**
|
|
* @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 <version>:: 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);
|
|
}
|