UNPKG

bsso

Version:

Bloomberg SSO js utilities

160 lines (159 loc) 6.75 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.BSSO = void 0; const query_string_1 = __importDefault(require("query-string")); const utils_1 = require("./utils"); class BSSO { constructor({ clientId, redirectUri, codeVerifier = null, accessToken = null, refreshToken = null, expirationTimestamp = null, }) { this._clientId = ''; this._redirectUri = ''; this._codeVerifier = ''; this._accessToken = null; this._refreshToken = null; this._expirationTimestamp = null; this._clientId = clientId; this._redirectUri = encodeURI(redirectUri); // the verifier is very important, we will need to hold on to it // after the redirect to verify our identity as per the PKCE workflow this._codeVerifier = codeVerifier !== null && codeVerifier !== void 0 ? codeVerifier : (0, utils_1.generateRandomString)(43); // if possible rehydrate this._accessToken = accessToken; this._refreshToken = refreshToken; this._expirationTimestamp = expirationTimestamp; } get clientId() { return this._clientId; } get redirectUri() { return this._redirectUri; } get codeVerifier() { return this._codeVerifier; } get accessToken() { return this._accessToken; } get refreshToken() { return this._refreshToken; } get expirationTimestamp() { return this._expirationTimestamp; } createTokenFromRedirectCode(code) { return __awaiter(this, void 0, void 0, function* () { const body = new URLSearchParams(); body.append('grant_type', 'authorization_code'); body.append('code', code); body.append('code_verifier', this.codeVerifier); body.append('client_id', this.clientId); body.append('redirect_uri', this.redirectUri); const rawResponse = yield fetch('https://bsso.blpprofessional.com/as/token.oauth2', { method: 'POST', mode: 'cors', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }); return this.handleTokenResponse(rawResponse); }); } regenerateToken() { return __awaiter(this, void 0, void 0, function* () { if (!this.refreshToken) { throw new Error('Have to have a refresh token to regenerate the access token.'); } const body = new URLSearchParams(); body.append('grant_type', 'refresh_token'); body.append('refresh_token', this.refreshToken); body.append('client_id', this.clientId); // because we are getting new tokens, clear the currently // existing ones from memory this._accessToken = null; this._refreshToken = null; const response = yield fetch('https://bsso.blpprofessional.com/as/token.oauth2', { method: 'POST', mode: 'cors', body: body.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }); return this.handleTokenResponse(response); }); } handleTokenResponse(fetchResponse) { return __awaiter(this, void 0, void 0, function* () { const regenerated = yield fetchResponse.json(); if (regenerated.error) { throw new Error(regenerated.error); } this._accessToken = regenerated.access_token; this._refreshToken = regenerated.refresh_token; this._expirationTimestamp = Date.now() / 1000 + regenerated.expires_in; return this.accessToken; }); } getToken(code) { return __awaiter(this, void 0, void 0, function* () { if (!this.accessToken && !this.refreshToken && !code) { throw new Error('Have to have a redirect code to get token the first time.'); } if (this.accessToken && !this.isExpired()) { return Promise.resolve(this.accessToken); } if (!this.accessToken && !this.refreshToken && code) { return this.createTokenFromRedirectCode(code); } return this.regenerateToken(); }); } isExpired() { if (!this.expirationTimestamp) return true; const current = new Date().getTime() / 1000; return current > this.expirationTimestamp; } getRedirectURL(token, scope = 'sapi blpapi-eps') { return __awaiter(this, void 0, void 0, function* () { // hash the verifier via SHA-256, the algorithm we specify below as our code_challenge_method const challengeHash = (0, utils_1.base64UrlEncode)((0, utils_1.sha256)(this.codeVerifier)); return query_string_1.default.stringifyUrl({ url: 'https://bsso.blpprofessional.com/as/authorization.oauth2', query: { client_id: this.clientId, code_challenge: challengeHash, code_challenge_method: 'S256', response_type: 'code', redirect_uri: this.redirectUri, scope, adapter: 'token', ssotoken: token, }, }); }); } toJSON() { return { clientId: this.clientId, redirectUri: decodeURI(this.redirectUri), codeVerifier: this.codeVerifier, accessToken: this.accessToken, refreshToken: this.refreshToken, expirationTimestamp: this.expirationTimestamp, }; } } exports.BSSO = BSSO;