UNPKG

@sap/xssec

Version:

XS Advanced Container Security API for node.js

79 lines (65 loc) 3.04 kB
'use strict'; const SecurityContext = require('../context/SecurityContext'); const UaaSecurityContext = require('../context/UaaSecurityContext'); const Token = require('../token/Token'); const UaaToken = require('../token/UaaToken'); const XsuaaService = require('./XsuaaService'); /** * @typedef {import('../util/Types').ServiceCredentials} ServiceCredentials * @typedef {import('../util/Types').UaaServiceCredentials} UaaServiceCredentials * @typedef {import('../util/Types').ServiceConfig} ServiceConfig * @typedef {import('../util/Types').SecurityContextConfig} SecurityContextConfig */ /** * New SAP BTP applications should start with SAP Identity Services instead of CF UAA! See README for details.\ * This {@link Service} class is constructed from CF UAA credentials to provide an API with selected functionality against that UAA service instance, e.g. token validation and token fetches. */ class UaaService extends XsuaaService { /** * @param {ServiceCredentials | UaaServiceCredentials} credentials * @param {ServiceConfig} [serviceConfig={}] */ constructor(credentials, serviceConfig) { super(credentials, serviceConfig); } /** * @override * @param {String|UaaToken} token token as JWT or UaaToken object * @param {SecurityContextConfig} contextConfig * @returns {Promise<UaaSecurityContext>} */ async createSecurityContext(token, contextConfig = {}) { if (typeof token === "string") { token = new UaaToken(token); } else if (token instanceof Token && !(token instanceof UaaToken)) { token = new UaaToken(token.jwt, { header: token.header, payload: token.payload }); } SecurityContext.buildContextConfig(contextConfig); if (contextConfig.skipValidation !== true && this.config.validation.enabled !== false) { await this.validateToken(token, contextConfig); } let ctx = new UaaSecurityContext(this, token, contextConfig); for (let extension of this.contextExtensions) { ctx = await extension.extendSecurityContext(ctx) ?? ctx; } return ctx; } /** * @overrides * @inheritdoc */ acceptsTokenAudience(token) { this.validateCredentials("validate token audience", "clientid"); if(!(token instanceof UaaToken)) { // cast to UaaToken, so token.scopes getter exists for the checks below token = new UaaToken(null, { header: token.header, payload: token.payload }); } // CF UAA tokens with grant_type === 'user_token' might not have audiences filled, so a fallback to scopes is needed const tokenAudiences = token.audiences?.length > 0 ? token.audiences : (token.scopes ?? []); if(token.payload.cid) { tokenAudiences.push(token.payload.cid); } return tokenAudiences.some(a => a === this.credentials.clientid || a.startsWith(`${this.credentials.clientid}.`)) } } module.exports = UaaService;