123 lines
No EOL
4.9 KiB
JavaScript
123 lines
No EOL
4.9 KiB
JavaScript
"use strict";
|
|
/**
|
|
* @module botframework-connector
|
|
*/
|
|
/**
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License.
|
|
*/
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.OpenIdMetadata = void 0;
|
|
const rsa_pem_from_mod_exp_1 = __importDefault(require("rsa-pem-from-mod-exp"));
|
|
const base64url_1 = __importDefault(require("base64url"));
|
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
const authenticationError_1 = require("./authenticationError");
|
|
const botframework_schema_1 = require("botframework-schema");
|
|
/**
|
|
* Class in charge of manage OpenId metadata.
|
|
*/
|
|
class OpenIdMetadata {
|
|
/**
|
|
* Initializes a new instance of the [OpenIdMetadata](xref:botframework-connector.OpenIdMetadata) class.
|
|
*
|
|
* @param url Metadata Url.
|
|
* @param proxySettings The proxy settings for the request.
|
|
*/
|
|
constructor(url, proxySettings) {
|
|
this.url = url;
|
|
this.proxySettings = proxySettings;
|
|
this.lastUpdated = 0;
|
|
}
|
|
/**
|
|
* Gets the Signing key.
|
|
*
|
|
* @param keyId The key ID to search for.
|
|
* @returns A `Promise` representation for either a [IOpenIdMetadataKey](botframework-connector:module.IOpenIdMetadataKey) or `null`.
|
|
*/
|
|
getKey(keyId) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// If keys are more than 24 hours old, refresh them
|
|
if (this.lastUpdated < Date.now() - 1000 * 60 * 60 * 24) {
|
|
yield this.refreshCache();
|
|
// Search the cache even if we failed to refresh
|
|
const key = this.findKey(keyId);
|
|
return key;
|
|
}
|
|
else {
|
|
// Otherwise read from cache
|
|
const key = this.findKey(keyId);
|
|
// Refresh the cache if a key is not found (max once per hour)
|
|
if (!key && this.lastUpdated < Date.now() - 1000 * 60 * 60) {
|
|
yield this.refreshCache();
|
|
return this.findKey(keyId);
|
|
}
|
|
return key;
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
refreshCache() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
let agent = null;
|
|
if (this.proxySettings) {
|
|
const proxyUrl = `http://${this.proxySettings.host}:${this.proxySettings.port}`;
|
|
agent = new https_proxy_agent_1.HttpsProxyAgent(proxyUrl);
|
|
}
|
|
const res = yield (0, node_fetch_1.default)(this.url, { agent: agent });
|
|
if (res.ok) {
|
|
const openIdConfig = (yield res.json());
|
|
const getKeyResponse = yield (0, node_fetch_1.default)(openIdConfig.jwks_uri, { agent: agent });
|
|
if (getKeyResponse.ok) {
|
|
this.lastUpdated = new Date().getTime();
|
|
this.keys = (yield getKeyResponse.json()).keys;
|
|
}
|
|
else {
|
|
throw new authenticationError_1.AuthenticationError(`Failed to load Keys: ${getKeyResponse.status}`, botframework_schema_1.StatusCodes.INTERNAL_SERVER_ERROR);
|
|
}
|
|
}
|
|
else {
|
|
throw new authenticationError_1.AuthenticationError(`Failed to load openID config: ${res.status}`, botframework_schema_1.StatusCodes.INTERNAL_SERVER_ERROR);
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
findKey(keyId) {
|
|
if (!this.keys) {
|
|
return null;
|
|
}
|
|
for (const key of this.keys) {
|
|
if (key.kid === keyId) {
|
|
if (!key.n || !key.e) {
|
|
// Return null for non-RSA keys
|
|
return null;
|
|
}
|
|
const modulus = base64url_1.default.toBase64(key.n);
|
|
const exponent = key.e;
|
|
return {
|
|
key: (0, rsa_pem_from_mod_exp_1.default)(modulus, exponent),
|
|
endorsements: key.endorsements,
|
|
};
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
exports.OpenIdMetadata = OpenIdMetadata;
|
|
//# sourceMappingURL=openIdMetadata.js.map
|