UNPKG

@sap-cloud-sdk/connectivity

Version:

SAP Cloud SDK for JavaScript connectivity

110 lines 4.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getServiceCredentials = getServiceCredentials; const util_1 = require("@sap-cloud-sdk/util"); // eslint-disable-next-line import-x/no-internal-modules const jwt_1 = require("../jwt/jwt"); const service_bindings_1 = require("./service-bindings"); const logger = (0, util_1.createLogger)({ package: 'connectivity', messageContext: 'environment-accessor' }); /** * @internal * Retrieves a service binding of the given type and tries to match it based on the JWT, if given. * Returns `undefined` if no match is found. * If no JWT is given, returns the first binding of the given service type, if available. * @param service - The service type. * @param token - Either an encoded or decoded JWT. * @returns The service credentials, otherwise `undefined`. */ function getServiceCredentials(service, token) { const credentialsList = getServiceBindingsWithCredentials(service); if (!credentialsList.length) { logger.debug(`Could not find binding to service '${service}', that includes credentials.`); return; } if (token) { const credentials = getCredentialsWithJwt(service, credentialsList, typeof token === 'string' ? (0, jwt_1.decodeJwt)(token) : token); return credentials; } logger.debug(`No JWT given to select binding to service '${service}'.`); return getCredentialsWithoutJwt(service, credentialsList); } /** * Credentials list getter for a given service. * @param service - Service name. * @returns Fetched credentials objects of existing service in 'VCAP_SERVICES'. */ function getServiceBindingsWithCredentials(service) { const services = (0, service_bindings_1.getServiceBindings)(service); const serviceCredentials = services .map(({ credentials }) => credentials) .filter(credentials => credentials); if (serviceCredentials.length < services.length) { const difference = services.length - serviceCredentials.length; logger.warn(`Ignoring ${difference} service binding${difference > 1 ? 's' : ''} of service type '${service}' because of missing credentials.`); } return serviceCredentials; } /** * @internal * Takes a JWT and uses the client_id and audience claims to determine the XSUAA service instance * that issued the JWT. Returns the credentials if a match is found, otherwise throws an error. * If no decoded JWT is specified, then returns the first existing XSUAA credential service plan "application". * @param token - Either an encoded or decoded JWT. * @returns The credentials for a match, otherwise `null`. */ function getCredentialsWithJwt(service, credentials, token) { const eligibleCredentials = credentials.filter(c => matchesClientId(c, token) || matchesAudience(c, token)); logResult(service, eligibleCredentials, true); return eligibleCredentials[0]; } function getCredentialsWithoutJwt(service, credentials) { logResult(service, credentials, false); return credentials[0]; } function logResult(service, credentials, usedToken) { if (credentials.length === 1) { logger.debug(`Found one service binding for service '${service}'${usingJwtText(usedToken)}. ${appNames(credentials)}`); } else if (credentials.length > 1) { logger.warn(`Found multiple bindings for service '${service}'${usingJwtText(usedToken)}. ${appNames(credentials)}\nChoosing first one ('${credentials[0].xsappname}').`); } else if (usedToken) { logger.warn(`Found no service binding for service '${service}' matching either the token's client id or audience.`); } } function usingJwtText(usedToken) { return usedToken ? ' using JWT' : ''; } function appNames(credentials) { const names = credentials.map(({ xsappname }) => xsappname); if (names.length) { return names.length === 1 ? `App name: ${names[0]}.` : `App names:${names.map(name => `\n\t- ${name}`).join('')}`; } return ''; } /** * @internal * Checks whether the client id in the token and in the given credentials match. * @param credentials - Credentials to check. * @param token - Token to check. * @returns Whether client ids match. */ function matchesClientId(credentials, token) { return credentials.clientid === token.client_id; } /** * @internal * Checks whether the audiences in the token and in the given credentials match. * @param credentials - Credentials to check. * @param token - Token to check. * @returns Whether audiences match. */ function matchesAudience(credentials, token) { return (0, jwt_1.audiences)(token).includes(credentials.xsappname); } //# sourceMappingURL=service-credentials.js.map