@sap/xssec
Advanced tools
Comparing version 3.2.18 to 3.3.0
# Change Log | ||
All notable changes to this project will be documented in this file. | ||
## 3.3.0 - 2023-07-24 | ||
- add app_tid to formular for token exchanges | ||
- support for "x-app_tid" and "x-client-id" header for IAS cert endpoint | ||
- bugfix for unknown variable in new cache implementation | ||
## 3.2.18 - 2023-07-13 | ||
@@ -5,0 +10,0 @@ - Replaced keycache implementation with new JwksReplica implementation: When a JWKS is used for validation, it is now checked if the cached replica will expire soon (default refresh period: 15min before expiration). If so, it will be refreshed in the background and the cached replica will still be used for validation until it has expired completely (default expiration time: 30min since last refresh). Validation of incoming requests will only be blocked by an expired JWKS if it could not be refreshed during the refresh period. Only one call at a time will be performed to refresh the JWKS. |
@@ -62,2 +62,6 @@ 'use strict'; | ||
this.getAppTID = function () { | ||
return zid; | ||
}; | ||
this.getSubdomain = function () { | ||
@@ -275,3 +279,3 @@ return subdomain; | ||
scopes = decodedToken.scope || []; | ||
zid = tokenInfo.getZoneId(); | ||
zid = tokenInfo.getAppTID(); | ||
subaccountid = decodedToken["ext_attr"] ? decodedToken["ext_attr"].subaccountid : zid; | ||
@@ -278,0 +282,0 @@ if (!subaccountid) { |
@@ -63,2 +63,6 @@ 'use strict'; | ||
this.getAppTID = function () { | ||
return zid; | ||
}; | ||
this.getSubdomain = function () { | ||
@@ -276,3 +280,3 @@ return subdomain; | ||
scopes = decodedToken.scope || []; | ||
zid = tokenInfo.getZoneId(); | ||
zid = tokenInfo.getAppTID(); | ||
subaccountid = decodedToken["ext_attr"] ? decodedToken["ext_attr"].subaccountid : zid; | ||
@@ -279,0 +283,0 @@ if (!subaccountid) { |
@@ -58,3 +58,3 @@ 'use strict'; | ||
getIdentityJwks(url, zone_uuid) { | ||
getIdentityJwks(url, app_tid, client_id) { | ||
if (!url) { | ||
@@ -64,7 +64,7 @@ throw new Error("Cannot get JWKS from empty URL."); | ||
const keyParts = [url, zone_uuid || ""]; | ||
const keyParts = [url, app_tid || ""]; | ||
const replicaKey = this.createCacheKey(keyParts); | ||
if (!this.#replicas.has(replicaKey)) { | ||
const service = new IdentityService(url, zone_uuid); | ||
const service = new IdentityService(url, app_tid, client_id); | ||
const jwksReplica = new JwksReplica(service, this.expirationTime, this.refreshPeriod); | ||
@@ -71,0 +71,0 @@ |
@@ -24,5 +24,2 @@ 'use strict'; | ||
function isXSUAAConfig(config) { | ||
return (config.xsappname ? true : (process.env.XSAPPNAME ? true : false)); | ||
} | ||
@@ -70,3 +67,2 @@ function toFormArray(obj) { | ||
const axios_options = { | ||
@@ -157,3 +153,3 @@ maxRedirects: 0, //no followRedirect | ||
function DefaultHeaders(zoneId, serviceCredentials) { | ||
function DefaultHeaders(zoneId, type) { | ||
var ret = { | ||
@@ -165,3 +161,3 @@ 'Accept': 'application/json', | ||
if (zoneId) { | ||
if (zoneId && type !== "ias") { | ||
ret[X_ZONE_ID_HEADER_NAME] = zoneId; | ||
@@ -173,3 +169,3 @@ } | ||
function buildOptions(serviceCredentials, additionalAttributes, url, grantType, zoneId, attributes) { | ||
function buildOptions(serviceCredentials, additionalAttributes, url, grantType, appTid, attributes) { | ||
// jwt bearer flow | ||
@@ -181,7 +177,8 @@ const path = attributes.configType === 'ias' ? '/oauth2/token' : '/oauth/token'; | ||
url: url + path, | ||
headers: DefaultHeaders(zoneId, serviceCredentials), | ||
headers: DefaultHeaders(appTid, attributes.configType), | ||
form: { | ||
grant_type: grantType, | ||
response_type: 'token', | ||
client_id: serviceCredentials.clientid | ||
client_id: serviceCredentials.clientid, | ||
app_tid: appTid || serviceCredentials.app_tid | ||
}, | ||
@@ -248,3 +245,3 @@ timeout: attributes.timeout | ||
module.exports.fetchOIDCKey = function (serviceCredentialsUrl, zone_id, attributes, cb) { | ||
module.exports.fetchOIDCKey = function (serviceCredentialsUrl, app_tid, attributes, cb) { | ||
var options = { | ||
@@ -261,7 +258,11 @@ method: 'GET', | ||
if (zone_id) { | ||
options.headers['x-zone_uuid'] = zone_id; | ||
if (app_tid) { | ||
options.headers["x-app_tid"] = app_tid; | ||
} | ||
if (attributes) { | ||
if (attributes) { | ||
if(attributes.clientId) { | ||
options.headers["x-client_id"] = attributes.clientId; | ||
} | ||
if (attributes.correlationId) { | ||
@@ -292,8 +293,8 @@ options.headers[CORRELATIONID_HEADER] = attributes.correlationId; | ||
if (config.type) { | ||
config.type = config.type.toLowerString(); | ||
if (config.type === "IAS") { | ||
config.type = "ias"; | ||
} | ||
return { | ||
configType: config.type ? config.type : (isXSUAAConfig(config.credentials) ? "xsuaa" : "ias"), | ||
configType: config.type || "xsuaa", | ||
scopes: config.scopes, | ||
@@ -310,3 +311,3 @@ correlationId: config.correlationId, | ||
timeout: defaultTimeout, | ||
configType: isXSUAAConfig(config) ? "xsuaa" : "ias" | ||
configType: "xsuaa" | ||
}; | ||
@@ -313,0 +314,0 @@ } |
@@ -12,11 +12,14 @@ 'use strict'; | ||
#url; | ||
#zone_uuid; // optional zone id | ||
#app_tid; // optional zone id | ||
#correlationId; // optional | ||
#oidcInfo; | ||
#clientId; | ||
get url() { return this.#url; } | ||
get zone_uuid() { return this.#zone_uuid; } | ||
get app_tid() { return this.#app_tid; } | ||
get correlationId() { return this.#correlationId; } | ||
get clientId() { return this.#clientId; } | ||
constructor(url, zone_uuid, correlationId) { | ||
constructor(url, app_tid, correlationId, client_id) { | ||
if (url === undefined) { | ||
@@ -27,4 +30,5 @@ throw new Error("IdentityService requires a url."); | ||
this.#url = url; | ||
this.#zone_uuid = zone_uuid; | ||
this.#app_tid = app_tid; | ||
this.#correlationId = correlationId; | ||
this.#clientId = client_id; | ||
} | ||
@@ -35,3 +39,3 @@ | ||
try { | ||
requests.requestOpenIDConfiguration(this.url, { correlationId: this.correlationId }, (err, oidcInfo) => { | ||
requests.requestOpenIDConfiguration(this.url, { correlationId: this.correlationId, clientId: this.clientId }, (err, oidcInfo) => { | ||
if (err) { | ||
@@ -62,3 +66,3 @@ rej(err); | ||
try { | ||
requests.fetchOIDCKey(jwksEndpoint, this.zone_uuid, { correlationId: this.correlationId }, (err, json) => { | ||
requests.fetchOIDCKey(jwksEndpoint, this.app_tid, { correlationId: this.correlationId, clientId: this.clientId }, (err, json) => { | ||
if (err) { | ||
@@ -104,3 +108,4 @@ rej(err); | ||
url: this.url, | ||
zone_uuid : this.zone_uuid | ||
app_tid : this.app_tid, | ||
client_id: this.clientId | ||
} | ||
@@ -107,0 +112,0 @@ } |
@@ -29,3 +29,3 @@ 'use strict'; | ||
if (err) { | ||
rej(e); | ||
return rej(err); | ||
} | ||
@@ -50,2 +50,2 @@ | ||
module.exports = XsuaaService; | ||
module.exports = XsuaaService; |
@@ -26,3 +26,3 @@ 'use strict'; | ||
//try to convert (IAS) token to an XSUAA token using the ZoneId from the token | ||
requests.requestUserToken(accessToken, serviceCredentials, null, null, null, ias_token.getZoneId(), function(err, xsuaaToken, json) { | ||
requests.requestUserToken(accessToken, serviceCredentials, null, null, null, ias_token.getAppTID(), function(err, xsuaaToken, json) { | ||
if(err) { | ||
@@ -29,0 +29,0 @@ cb(err); |
@@ -106,6 +106,10 @@ 'use strict'; | ||
this.getZoneId = function () { | ||
return this.getAppTID(); | ||
} | ||
this.getAppTID = function() { | ||
if (this.isTokenIssuedByXSUAA()) { | ||
return payload.zid; | ||
return payload.zid; | ||
} else { | ||
return payload.zone_uuid; | ||
return payload.app_tid ? payload.app_tid : payload.zone_uuid; | ||
} | ||
@@ -112,0 +116,0 @@ } |
@@ -244,3 +244,3 @@ 'use strict'; | ||
try { | ||
const jwks = await jwksManager.getIdentityJwks(issuer, token.getZoneId()); | ||
const jwks = await jwksManager.getIdentityJwks(issuer, token.getAppTID(), serviceCredentials.clientid); | ||
jwk = await jwks.get(header.kid); | ||
@@ -247,0 +247,0 @@ } catch(e) { |
{ | ||
"name": "@sap/xssec", | ||
"version": "3.2.18", | ||
"version": "3.3.0", | ||
"description": "XS Advanced Container Security API for node.js", | ||
@@ -5,0 +5,0 @@ "main": "./lib", |
147041
2282
7