SAP-BTP-Spielwiese/app1/node_modules/@sap/xssec/lib/service/IdentityService.js
Markus Rettig 775ac7b58c completed step 3 from the tutorial
you must login with an BTP account in order to see the app
2024-02-08 16:13:36 +01:00

109 lines
No EOL
3.4 KiB
JavaScript

'use strict';
const debug = require('debug');
const debugError = debug('xssec:JwksReplica');
debugError.log = console.error.bind(console);
const requests = require('../requests');
const nodeRSA = require('node-rsa');
const PROTOCOL = "https://";
class IdentityService {
#serviceCredentials;
#url;
#oidcInfo;
get serviceCredentials() { return this.#serviceCredentials; }
get url() { return this.#url; }
constructor(serviceCredentials) {
if (serviceCredentials == null) {
throw new Error("IdentityService requires service credentials.");
}
this.#serviceCredentials = serviceCredentials;
this.#url = serviceCredentials.url;
}
/** Configures OIDC calls from this service to target the given domain instead of the url from the service credentials. */
withCustomDomain(domain) {
this.#url = domain.startsWith(PROTOCOL) ? domain : `${PROTOCOL}${domain}`;
return this;
}
async fetchOidcInfo() {
if (!this.#oidcInfo) {
this.#oidcInfo = await new Promise((res, rej) => {
try {
requests.requestOpenIDConfiguration(this.url, { clientId: this.serviceCredentials.clientId }, (err, oidcInfo) => {
if (err) {
return rej(err);
}
return res(oidcInfo);
});
} catch (e) {
return rej(e);
}
});
}
return this.#oidcInfo;
}
async fetchJwks(params = {}) {
if(params.client_id && params.client_id !== this.serviceCredentials.clientid) {
return Promise.reject("Invalid state: IdentityService#fetchJwks called with client_id value that is different from the client_id of the IdentityService object.");
}
await this.fetchOidcInfo();
const jwksEndpoint = this.#oidcInfo["jwks_uri"];
return new Promise((res, rej) => {
try {
requests.fetchOIDCKey(jwksEndpoint, params, (err, json) => {
if (err) {
return rej(err);
}
const jwks = json.keys
.map(key => {
try {
const pem = this.createPem(key);
key.value = pem;
} catch (e) {
debugError(`Could not calculate PEM for key with kid ${key.kid}: ${e}. IdentityService: (${JSON.stringify(this)})`)
}
return key;
})
.filter(key => key.value !== undefined);
return res(jwks);
});
} catch (e) {
return rej(e);
}
});
}
createPem(key) {
if (key.kty !== "RSA") {
throw new Error("KTY '" + key.kty + "' not supported");
}
const modulus = Buffer.from(key.n, 'base64');
const exponent = Buffer.from(key.e, 'base64');
const pubKey = new nodeRSA().importKey({ n: modulus, e: exponent }, 'components-public');
return pubKey.exportKey('pkcs8-public-pem');
}
toJSON() {
return {
url: this.url
}
}
}
module.exports = IdentityService;