UNPKG

@factset/sdk-utils

Version:

Utilities for interacting with FactSet APIs.

101 lines (100 loc) 4.86 kB
"use strict"; 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.ConfidentialClient = void 0; const _1 = require("."); const openIDClientFactory_1 = require("./openIDClientFactory"); const configuration_1 = require("./configuration"); const constants_1 = require("./constants"); const unixTimestamp_1 = require("./unixTimestamp"); const debug_1 = __importDefault(require("debug")); const https_proxy_agent_1 = require("https-proxy-agent"); const debug = (0, debug_1.default)(`${constants_1.PACKAGE_NAME}:ConfidentialClient`); /** * Helper class that supports FactSet's implementation of the OAuth 2.0 * client credentials flow. * * The main purpose of this class is to provide an access token that can * be used to authenticate against FactSet's APIs. It takes care of fetching * the access token, caching it and refreshing it as needed. */ class ConfidentialClient { constructor(param, _options) { this._config = configuration_1.Configuration.loadConfig(param); this._token = new _1.Token('', 0); this._options = _options !== null && _options !== void 0 ? _options : null; } /** * Returns an access token that can be used for authentication. * * If the cache contains a valid access token, it's returned. Otherwise * a new access token is retrieved from FactSet's authorization server. * * The access token should be used immediately and not stored to avoid * any issues with token expiry. * * The access token is used in the Authorization header when when accessing * FactSet's APIs. Example: `{"Authorization": "Bearer access-token"}` * * @returns access token for protected resource requests */ getAccessToken() { var _a; return __awaiter(this, void 0, void 0, function* () { if (this._token.isExpired() === false) { debug('Retrieving cached token. Expires at %d, in %d seconds.', this._token.expiresAt, this._token.expiresIn); return this._token.token; } debug('Token is expired or invalid'); if ((_a = this._options) === null || _a === void 0 ? void 0 : _a.proxyUrl) { const proxyAgent = new https_proxy_agent_1.HttpsProxyAgent(`${this._options.proxyUrl}`); this._openIDClient = yield openIDClientFactory_1.OpenIDClientFactory.getClient(this._config, proxyAgent); } else { this._openIDClient = yield openIDClientFactory_1.OpenIDClientFactory.getClient(this._config); } this._token = yield this.fetchAccessToken(); return this._token.token; }); } fetchAccessToken() { return __awaiter(this, void 0, void 0, function* () { debug('Fetching new access token'); try { const now = (0, unixTimestamp_1.unixTimestamp)(); const tokenSet = yield this._openIDClient.grant({ grant_type: 'client_credentials', }, { clientAssertionPayload: { nbf: now - constants_1.JWT_NOT_BEFORE_SECS, iat: now, exp: now + constants_1.JWT_EXPIRE_AFTER_SECS, }, }); if (tokenSet.access_token === undefined || tokenSet.expires_at === undefined) { throw new _1.AccessTokenError('Got an invalid token'); } debug('Got access token that expires at %d, in %d seconds', tokenSet.expires_at, tokenSet.expires_in); return new _1.Token(tokenSet.access_token, tokenSet.expires_at); } catch (error) { if (error instanceof _1.AccessTokenError) { throw error; } throw new _1.AccessTokenError('Error attempting to get access token', error); } }); } } exports.ConfidentialClient = ConfidentialClient;