'use strict'; const constants = require('./constants'); const xsuaa = require('./ctx/xsuaa'); const ias = require('./ctx/ias'); const uaa = require('./ctx/uaa'); // use environment variable DEBUG with value 'xssec:*' for trace/error messages const debug = require('debug'); const debugTrace = debug('xssec:securitycontext'); const debugError = debug('xssec:securitycontext'); debugError.log = console.error.bind(console); debugTrace.log = console.log.bind(console); function throw500(errorString) { debugError('\n' + errorString); var error = new Error(errorString); error.statuscode = 500; //500 (Invalid config) throw error; } function validateConfig(config) { // validate config input debugTrace('\nConfiguration (note: clientsecret might be contained but is not traced): ' + JSON.stringify(config, function (key, value) { return key === 'clientsecret' ? undefined : value; }, 2)); // validate config input if (!config) { return throw500('Invalid config (missing).'); } if (!config.clientid) { return throw500('Invalid config: Missing clientid.'); } if (!config.url) { return throw500('Invalid config: Missing url.'); } } function validateXSUAAConfig(config) { if (!config.xsappname) { if (!process.env.XSAPPNAME) { var errorString = 'Invalid config: Missing xsappname.\n' + 'The application name needs to be defined in xs-security.json.'; return throw500(errorString); } debugTrace('\nXSAPPNAME defined in manifest.yml (legacy).\n' + 'You should switch to defining xsappname in xs-security.json.'); return process.env.XSAPPNAME; } else { if (!process.env.XSAPPNAME) { return config.xsappname; } if (process.env.XSAPPNAME == config.xsappname) { debugTrace('\nThe application name is defined both in the manifest.yml (legacy) \n' + 'as well as in xs-security.json. Remove it in manifest.yml.'); return process.env.XSAPPNAME; } var errorString = 'Invalid config: Ambiguous xsappname.\n' + 'The application name is defined with different values in the manifest.yml (legacy)\n' + 'as well as in xs-security.json. Remove it in manifest.yml.'; return throw500(errorString); } } function validateIASConfig(config) { //TODO: clarify do we need to check something here? } function takeXSUAAConfiguration(config, forceType) { if(forceType === exports.XSUAA || forceType === exports.UAA) { debugTrace("Creating a XSUAA securityContext because of forceType"); return true; } else if(forceType === exports.IAS) { debugTrace("Creating a IAS securityContext because of forceType"); return false; } else if(!forceType) { if(config.xsappname ? true : (process.env.XSAPPNAME ? true : false)) { debugTrace("Creating a XSUAA securityContext because of xsappname"); return true; } else { debugTrace("Creating a IAS securityContext because of missing xsappname"); return false; } } throw500("Unknown SecurityContextType (" + forceType + ")"); } exports.XSUAA = "XSUAA"; exports.IAS = "IAS"; exports.UAA = "UAA"; function getConfigV2(config) { if(!config) { return { credentials: null }; } if(config.credentials) { return config; } return { credentials: config, correlationId: null, cache: config.cache, disableCache: false } } //For Backward compatibilty exports.createSecurityContext = function (token, configParameter, forceType, cb) { if(typeof forceType === 'function') { cb = forceType; forceType = null; } if(!cb || typeof cb !== 'function') { throw500("The callback parameter should be a function"); } try { const configv2 = getConfigV2(configParameter); const configParam = configv2.credentials; //make sure the parameter is an array var configArr = Array.isArray(configParam) ? configParam : [configParam]; //our main config is always the config at position 0 var config = configArr[0]; validateConfig(config); let securityContext; if(takeXSUAAConfiguration(config, forceType)) { //will return the xsappname to use (env or config) config.xsappname = validateXSUAAConfig(config); //create a XSUAA security Context if(forceType === exports.UAA) { securityContext = new uaa.SecurityContext(config, configArr); } else { securityContext = new xsuaa.SecurityContext(config, configArr); } } else { validateIASConfig(config); //create a IAS security Context securityContext = new ias.SecurityContext(config, configArr); } securityContext.verifyToken(token, configv2, cb); } catch (e) { cb(e); } }