Socket
Socket
Sign inDemoInstall

@sap/xssec

Package Overview
Dependencies
24
Maintainers
1
Versions
69
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.2.8 to 3.2.9

5

CHANGELOG.md
# Change Log
All notable changes to this project will be documented in this file.
## 3.2.9 - 2021-10-22
- custom domain support for IAS
- support for "x-correlation-id" header to be set for createSecurityContext and tokenexchange-calls
- support to turn off the internal cache for a createSecurityContext call
## 3.2.8 - 2021-10-18

@@ -5,0 +10,0 @@ - add additional getter for user properties on XSUAA context

4

lib/ctx/ias.js

@@ -57,4 +57,4 @@ 'use strict';

this.verifyToken = function (encodedToken, cb) {
var verificationKey = new VerificationKey(config, "IAS");
this.verifyToken = function (encodedToken, attributes, cb) {
var verificationKey = new VerificationKey(config, "IAS", attributes);
var jwtValidator = createJwtTokenValidator(verificationKey, configArr, config);

@@ -61,0 +61,0 @@

@@ -340,4 +340,4 @@ 'use strict';

this.verifyToken = function (encodedToken, cb) {
var verificationKey = new VerificationKey(config, this.getConfigType());
this.verifyToken = function (encodedToken, attributes, cb) {
var verificationKey = new VerificationKey(config, this.getConfigType(), attributes);
var jwtValidator = createJwtTokenValidator(verificationKey, configArr, config);

@@ -344,0 +344,0 @@

@@ -93,6 +93,7 @@ 'use strict';

KeyCache.prototype.getWellKnownFromOIDC = function(serviceUrl, cb) {
var cacheKey = serviceUrl + ".well_known.";
KeyCache.prototype.getWellKnownFromOIDC = function(serviceUrl, attrib, cb) {
const attributes = attrib || { disableCache: false };
const cacheKey = serviceUrl + ".well_known.";
var tmpResult = this.lruCache.get(cacheKey);
var tmpResult = attributes.disableCache === true ? null : this.lruCache.get(cacheKey);
if(tmpResult) {

@@ -103,3 +104,3 @@ cb(null, tmpResult);

requests.requestOpenIDConfiguration(serviceUrl, function(err, result) {
requests.requestOpenIDConfiguration(serviceUrl, attributes, function(err, result) {
if(err) {

@@ -109,3 +110,5 @@ return cb(err);

self.addKey(cacheKey, result);
if(attributes.disableCache !== true) {
self.addKey(cacheKey, result);
}
cb(null, result);

@@ -116,6 +119,7 @@ });

KeyCache.prototype.getKeyOIDC = function(serviceUrl, keyId, zone_id, cb) {
var self = this;
KeyCache.prototype.getKeyOIDC = function(serviceUrl, keyId, zone_id, attrib, cb) {
const attributes = attrib || { disableCache: false };
const self = this;
this.getWellKnownFromOIDC(serviceUrl, function(err, result) {
this.getWellKnownFromOIDC(serviceUrl, attributes, function(err, result) {
if(err) {

@@ -127,9 +131,11 @@ return cb(err);

let tmpResult = self.lruCache.get(zone_id + tokenUrl + keyId);
if(tmpResult) {
//found in Cache
return cb(null, tmpResult);
if(attributes.disableCache !== true) {
let tmpResult = self.lruCache.get(zone_id + tokenUrl + keyId);
if(tmpResult) {
//found in Cache
return cb(null, tmpResult);
}
}
requests.fetchOIDCKey(tokenUrl, zone_id, function(err, result) {
requests.fetchOIDCKey(tokenUrl, zone_id, attributes, function(err, result) {
if(err) {

@@ -139,2 +145,3 @@ return cb(err);

let found = null;
//add all Keys to cache

@@ -144,3 +151,9 @@ for(var i=0;i<result.keys.length;++i) {

try {
self.addKey(zone_id + tokenUrl + key.kid, createPublicKeyFromJWKS(key));
const pem = createPublicKeyFromJWKS(key);
if(attributes.disableCache !== true) {
self.addKey(zone_id + tokenUrl + key.kid, pem);
}
if(key.kid === keyId) {
found = pem;
}
} catch(e) {

@@ -151,4 +164,4 @@ debugError(e);

var cacheKey = zone_id + tokenUrl + keyId;
var tmpResult = self.lruCache.get(cacheKey);
const cacheKey = zone_id + tokenUrl + keyId;
const tmpResult = attributes.disableCache === true ? found : self.lruCache.get(cacheKey);
if(tmpResult) {

@@ -163,4 +176,5 @@ cb(null, tmpResult);

KeyCache.prototype.getKey = function getKey(tokenKeyUrl, keyId, zid, cb) {
KeyCache.prototype.getKey = function getKey(tokenKeyUrl, keyId, zid, attrib, cb) {
var self = this;
const attributes = attrib || { disableCache: false };

@@ -183,3 +197,3 @@ if ((tokenKeyUrl === null) || (tokenKeyUrl === undefined)) {

// Check whether keyid is in cache
var tmpResult = this.lruCache.get(cacheKey);
var tmpResult = attributes.disableCache === true ? null : this.lruCache.get(cacheKey);
if (tmpResult !== undefined) {

@@ -195,3 +209,3 @@ debugTrace('Key with keyID: "' + keyId + '" found in cache. Returning key "' + tmpResult + '".');

return requests.fetchKeyFromXSUAA(tokenKeyUrl, zid, function(err, json) {
return requests.fetchKeyFromXSUAA(tokenKeyUrl, zid, attributes, function(err, json) {
if(err) {

@@ -207,10 +221,21 @@ debugError(`An error occurred when reading the token keys from ${tokenKeyUrl}: ${err.message}${err.stack}`);

debugTrace("Number of KeyIDs returned from XSUAA", json.keys.length);
let found = null;
for (var i = 0; i < json.keys.length; i++) {
// Note: The following code removes line
// breaks before adding the key to the cache
self.addKey(tokenKeyUrl + json.keys[i].kid, json.keys[i].value.replace(/(\r\n|\n|\r)/gm, ''));
const id = tokenKeyUrl + json.keys[i].kid;
const pem = json.keys[i].value.replace(/(\r\n|\n|\r)/gm, '');
if(id === cacheKey) {
found = pem;
}
if(attributes.disableCache !== true) {
self.addKey(id, pem);
}
}
var tmpResult = self.lruCache.get(cacheKey);
if (tmpResult !== undefined) {
var tmpResult = attributes.disableCache === true ? found : self.lruCache.get(cacheKey);
if (tmpResult) {
debugTrace('Key "' + cacheKey + '" found in cache. Returning key "' + tmpResult + '".');

@@ -217,0 +242,0 @@ return cb(null, tmpResult);

@@ -101,3 +101,3 @@ 'use strict';

function appendAdditonalAttribites(options, additionalAttributes) {
function appendAdditonalAttributes(options, additionalAttributes) {
if (additionalAttributes !== null) {

@@ -109,3 +109,3 @@ var authorities = {"az_attr": additionalAttributes};

function DefaultHeaders(zoneId) {
function DefaultHeaders(zoneId, serviceCredentials) {
var ret = {

@@ -124,3 +124,3 @@ 'Accept': 'application/json',

function buildOptions(serviceCredentials, additionalAttributes, url, grantType, zoneId, timeout) {
function buildOptions(serviceCredentials, additionalAttributes, url, grantType, zoneId, timeout, attributes) {
// jwt bearer flow

@@ -130,3 +130,3 @@ const options = {

url: url + '/oauth/token',
headers: DefaultHeaders(zoneId),
headers: DefaultHeaders(zoneId, serviceCredentials),
form: {

@@ -154,8 +154,14 @@ grant_type: grantType,

appendAdditonalAttribites(options, additionalAttributes);
appendAdditonalAttributes(options, additionalAttributes);
if(attributes) {
if(attributes.correlationId) {
options.headers['x-correlation-id'] = attributes.correlationId;
}
}
return options;
}
module.exports.requestOpenIDConfiguration = function (serviceCredentialsUrl, cb) {
module.exports.requestOpenIDConfiguration = function (serviceCredentialsUrl, attributes, cb) {
var options = {

@@ -172,6 +178,12 @@ method: 'GET',

if(attributes) {
if(attributes.correlationId) {
options.headers['x-correlation-id'] = attributes.correlationId;
}
}
return _requestToNetwork(".well-known", options, cb);
}
module.exports.fetchOIDCKey = function (serviceCredentialsUrl, zone_id, cb) {
module.exports.fetchOIDCKey = function (serviceCredentialsUrl, zone_id, attributes, cb) {
var options = {

@@ -192,6 +204,28 @@ method: 'GET',

if(attributes) {
if(attributes.correlationId) {
options.headers['x-correlation-id'] = attributes.correlationId;
}
}
return _requestToNetwork(".oidc-jkws", options, cb);
}
module.exports.requestUserToken = function (appToken, serviceCredentials, additionalAttributes, scopes, subdomain, zoneId, cb) {
function getServiceCredentials(config) {
if(config.credentials) {
return config.credentials;
}
return config;
}
function getAttributes(config) {
if(config.credentials) {
return config;
}
return null;
}
module.exports.requestUserToken = function (appToken, config, additionalAttributes, scopes, subdomain, zoneId, cb) {
//make it backward-compatible (where zoneId is not provided at all)

@@ -203,2 +237,5 @@ if (typeof zoneId === 'function') {

const serviceCredentials = getServiceCredentials(config);
const attributes = getAttributes(config);
var error = validateParameters(serviceCredentials, cb);

@@ -219,3 +256,4 @@ if (error) {

zoneId,
DEFAULT_USER_TOKEN_TIMEOUT);
DEFAULT_USER_TOKEN_TIMEOUT,
attributes);

@@ -237,3 +275,3 @@ //add Assertion

module.exports.requestClientCredentialsToken = function (subdomain, serviceCredentials, additionalAttributes, zoneId, cb) {
module.exports.requestClientCredentialsToken = function (subdomain, config, additionalAttributes, zoneId, cb) {
//make it backward-compatible (where zoneId is not provided at all)

@@ -245,2 +283,5 @@ if (typeof zoneId === 'function') {

const serviceCredentials = getServiceCredentials(config);
const attributes = getAttributes(config);
// input validation

@@ -262,5 +303,6 @@ const error = validateParameters(serviceCredentials, cb);

zoneId,
DEFAULT_TIMEOUT);
DEFAULT_TIMEOUT,
attributes);
appendAdditonalAttribites(options, additionalAttributes);
appendAdditonalAttributes(options, additionalAttributes);
return _requestToNetwork("requestClientCredentialsToken", options, cb);

@@ -274,3 +316,3 @@ } catch (e) {

module.exports.fetchKeyFromXSUAA = async function (tokenKeyUrl, zid, cb) {
module.exports.fetchKeyFromXSUAA = async function (tokenKeyUrl, zid, attributes, cb) {
const options = {

@@ -284,2 +326,8 @@ headers: {

timeout: DEFAULT_TIMEOUT
};
if(attributes) {
if(attributes.correlationId) {
options.headers['x-correlation-id'] = attributes.correlationId;
}
}

@@ -286,0 +334,0 @@

@@ -48,2 +48,3 @@ 'use strict';

var authParams = options;
if (!authorization) {

@@ -71,2 +72,4 @@ debugTrace('Missing Authorization header');

const correlationId = req.headers["x-correlation-id"] || req.headers["vcap_request_id"];
try {

@@ -111,3 +114,3 @@

xssec.createSecurityContext(token, this.options, paramA, paramB);
xssec.createSecurityContext(token, {credentials: this.options, correlationId: correlationId}, paramA, paramB);
}

@@ -114,0 +117,0 @@ catch (err) {

@@ -75,4 +75,8 @@ 'use strict';

this.getIssuer = function() {
return payload.iss;
return payload["ias_iss"] ? payload["ias_iss"] : payload.iss;
}
this.getCustomIssuer = function() {
return payload["ias_iss"] ? payload.iss : null;
}

@@ -79,0 +83,0 @@ this.getSubject = function() {

@@ -13,3 +13,3 @@ 'use strict';

function VerificationKey(config, type) {
function VerificationKey(config, type, attributes) {
var tokenInfo = null;

@@ -75,6 +75,6 @@ var loadKeyError = null;

var zone_id = tokenInfo.getPayload().zone_uuid || "";
var zone_id = tokenInfo.getPayload().zone_uuid || "";
//try to get a key from KeyCache
keyCache.getKeyOIDC(tokenInfo.getIssuer(), accessToken.kid, zone_id, function(err, key) {
keyCache.getKeyOIDC(tokenInfo.getIssuer(), accessToken.kid, zone_id, attributes, function(err, key) {
if (err) {

@@ -106,3 +106,3 @@ debugTrace('\n' + err);

//try to get a key from KeyCache
keyCache.getKey(accessToken.jku, accessToken.kid, zid, function(err, key) {
keyCache.getKey(accessToken.jku, accessToken.kid, zid, attributes, function(err, key) {
if (err) {

@@ -109,0 +109,0 @@ //store the

@@ -129,4 +129,23 @@ 'use strict';

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, configParam, forceType, cb) {
exports.createSecurityContext = function (token, configParameter, forceType, cb) {
if(typeof forceType === 'function') {

@@ -142,2 +161,4 @@ cb = forceType;

try {
const configv2 = getConfigV2(configParameter);
const configParam = configv2.credentials;
//make sure the parameter is an array

@@ -163,3 +184,3 @@ var configArr = Array.isArray(configParam) ? configParam : [configParam];

securityContext.verifyToken(token, cb);
securityContext.verifyToken(token, configv2, cb);
} catch (e) {

@@ -166,0 +187,0 @@ cb(e);

{
"name": "@sap/xssec",
"version": "3.2.8",
"version": "3.2.9",
"description": "XS Advanced Container Security API for node.js",

@@ -5,0 +5,0 @@ "main": "./lib",

@@ -75,2 +75,53 @@ @sap/xssec: XS Advanced Container Security API for node.js

### Support for X-Correlation-ID header
The xssec library internally calls REST APIs of the XSUAA.
Now it's possible to set a `correlationId` during context creation and for token exchange calls.
For this you have to restructe the configuration object.
```js
const config = {
credentials: xsenv.getServices({xsuaa:{tag:'xsuaa'}}).xsuaa,
correlationId: "1111-1111-11111111"
};
//now you can call the createSecurityContext method as always
xssec.createSecurityContext(access_token, config, function(error, securityContext, tokenInfo) {
if (error) {
console.log('Security Context creation failed');
return;
}
console.log('Security Context created successfully');
console.log(tokenInfo.getPublicClaims());
});
```
### Disable the cache for the current call (ONLY FOR TESTING!)
The xssec library internally calls REST APIs to fetch the public verification keys from XSUAA/IAS.
For performance reasons there is a cache, so not all calls have to fetch the key again.
Now it's possible to turn off the cache using the `disableCache` option during context creation.
For this you have to restructe the configuration object.
```js
const config = {
credentials: xsenv.getServices({xsuaa:{tag:'xsuaa'}}).xsuaa,
correlationId: "1111-1111-11111111"
disableCache: true
};
//now you can call the createSecurityContext method as always
//internally no Cache will be used!
xssec.createSecurityContext(access_token, config, function(error, securityContext, tokenInfo) {
if (error) {
console.log('Security Context creation failed');
return;
}
console.log('Security Context created successfully');
console.log(tokenInfo.getPublicClaims());
});
```
This also works for the Tokenexchange methods!
### Usage with Passport Strategy

@@ -77,0 +128,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc