Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sap/xssec

Package Overview
Dependencies
Maintainers
1
Versions
85
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/xssec - npm Package Compare versions

Comparing version 3.5.0 to 3.6.0

3

CHANGELOG.md
# Change Log
All notable changes to this project will be documented in this file.
## 3.6.0 - 2023-11-24
- adapt optimized IAS server API
## 3.5.0 - 2023-11-14

@@ -5,0 +8,0 @@ - update dependencies (e.g. axios 0 -> 1)

10

lib/jwks/JwksManager.js

@@ -65,5 +65,5 @@ 'use strict';

getIdentityJwks(url, serviceCredentials, token, attributes = {}) {
if (!url) {
throw new Error("Cannot get JWKS from empty URL.");
getIdentityJwks(issuerDomain, serviceCredentials, token, attributes = {}) {
if (!issuerDomain) {
throw new Error("Cannot get JWKS from empty domain.");
}

@@ -79,3 +79,3 @@

if (!attributes.disableCache) {
const keyParts = {url, ...jwksParams};
const keyParts = {domain: issuerDomain, ...jwksParams};
replicaKey = this.createCacheKey(keyParts);

@@ -87,3 +87,3 @@

if (!jwksReplica) {
const service = new IdentityService(serviceCredentials).withCustomDomain(url);
const service = new IdentityService(serviceCredentials).withCustomDomain(issuerDomain);
jwksReplica = new JwksReplica(service, this.expirationTime, this.refreshPeriod).withParams(jwksParams);

@@ -90,0 +90,0 @@

@@ -10,9 +10,11 @@ 'use strict';

const PROTOCOL = "https://";
class IdentityService {
#serviceCredentials;
#domain;
#url;
#oidcInfo;
get serviceCredentials() { return this.#serviceCredentials; }
get url() { return this.#domain; }
get url() { return this.#url; }

@@ -25,3 +27,3 @@ constructor(serviceCredentials) {

this.#serviceCredentials = serviceCredentials;
this.#domain = serviceCredentials.url;
this.#url = serviceCredentials.url;
}

@@ -31,3 +33,3 @@

withCustomDomain(domain) {
this.#domain = domain;
this.#url = domain.startsWith(PROTOCOL) ? domain : `${PROTOCOL}${domain}`;
return this;

@@ -105,3 +107,3 @@ }

return {
domain: this.url
url: this.url
}

@@ -108,0 +110,0 @@ }

@@ -162,37 +162,2 @@ 'use strict';

function checkIssuer(issuer, domains) {
if (!issuer) {
throw "issuer is empty";
}
//make sure we have a protocol at the beginning of the url
if (issuer.indexOf('http') !== 0) {
issuer = "https://" + issuer;
}
const myURL = new url.URL(issuer);
if (myURL.protocol !== 'https:') {
if (myURL.hostname !== 'localhost') {
throw "Issuer has wrong protocol (" + myURL.protocol + ")";
}
}
if (myURL.hash) {
throw "Issuer has unallowed hash value (" + myURL.hash + ")";
}
if (myURL.search) {
throw "Issuer has unallowed query value (" + myURL.search + ")";
}
for (let i = 0; i < domains.length; ++i) {
if (myURL.hostname.endsWith(domains[i])) {
return;
}
}
throw "Issuer not found in domain list " + domains;
}
this.validateToken = function (accessToken, cb) {

@@ -207,3 +172,3 @@ function returnError(code, errorString) {

//make sure we have at least an array of 1 domain
const domains = Array.isArray(serviceCredentials.domains) ? serviceCredentials.domains : [serviceCredentials.domain];
const trustedDomains = Array.isArray(serviceCredentials.domains) ? serviceCredentials.domains : [serviceCredentials.domain];
const token = new TokenInfo(accessToken);

@@ -213,6 +178,7 @@

const issuer = token.getIssuer();
let issuerDomain;
try {
checkIssuer(issuer, domains)
issuerDomain = this.getIssuerDomain(issuer, trustedDomains);
} catch (e) {
return returnError(401, "Issuer validation failed (iss=" + issuer + ") message=" + e);
return returnError(401, `Issuer validation failed for issuer ${issuer}, message=${e}`);
}

@@ -235,3 +201,3 @@

try {
const jwks = await jwksManager.getIdentityJwks(issuer, serviceCredentials, token, attributes);
const jwks = await jwksManager.getIdentityJwks(issuerDomain, serviceCredentials, token, attributes);
jwk = await jwks.get(header.kid);

@@ -268,2 +234,42 @@ } catch(e) {

}
/**
* Returns the issuer domain based on the issuer of the token but validates it against a list of trusted domains.
* @param {string} issuer issuer from token
* @param {Array<string>} trustedDomains a list of trusted domains
* @returns domain of issuer if is either a trusted domain or a subdomain of a trusted domain
* @throws Error if issuer is empty, not trusted or not a valid URL
*/
this.getIssuerDomain = function (issuer, trustedDomains = []) {
if(!issuer) {
throw new Error("No issuer found.");
}
const httpsScheme = "https://";
const issuerUrl = issuer.startsWith(httpsScheme) ? issuer : `${httpsScheme}${issuer}`;
try {
new URL(issuerUrl);
} catch(e) {
throw new Error("Issuer was not a valid URL suitable for https.", e);
}
const issuerDomain = issuerUrl.substring(httpsScheme.length);
for(let d of trustedDomains) {
const validSubdomainPattern = `^[a-zA-Z0-9-]{1,63}\\.${escapeStringForRegex(d)}$`; // a string that ends with .<trustedDomain> and contains 1-63 letters, digits or '-' before that for the subdomain
if(issuerDomain === d || issuerDomain.match(new RegExp(validSubdomainPattern))) {
return issuerDomain;
}
}
throw new Error("Issuer domain was not a trusted domain or a subdomain of a trusted domain.")
}
/**
* Escapes Regex special characters in the given string, so that the string can be used for a literal match inside a Regex.
* Regex.escape is only a proposal at the time of writing.
* The source of this code is https://github.com/tc39/proposal-regex-escaping/blob/main/polyfill.js
*/
function escapeStringForRegex(s) {
return String(s).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
}
}

@@ -270,0 +276,0 @@

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

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

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc