UNPKG

search-client

Version:

Javascript library for executing searches in the Haive search-index via the SearchManager REST interface.

177 lines 8.29 kB
import { __awaiter, __extends, __generator } from "tslib"; import * as jwt from 'jwt-simple'; import { BaseCall, Query } from '../Common'; import { AuthenticationSettings, } from './AuthenticationSettings'; import { AuthToken } from './AuthToken'; /** * The JwtAuthentication service is a supporting feature for the other services. * Typically used via the [[SearchClient.constructor]] and by providing [[AuthenticationSettings]] settings in * the [[Settings.authentication]] property. * * The authentication system is based on JWT and needs an end-point to be configured from where it will get its * authentication-token. This service will be monitoring the token-value to see if it is either missing or * expired. When that happens a new token will be fetched from the end-point. The [[AuthenticationSettings.expiryOverlap]] * object controls how long before expiration the new token is to be fetched. */ var JwtAuthentication = /** @class */ (function (_super) { __extends(JwtAuthentication, _super); /** * Creates an JwtAuthentication object that knows where to get the auth-token and when to refresh it. * @param settings - The settings for the authentication object. * @param auth - An object that controls the authentication for the lookups. */ function JwtAuthentication(settings, auth, fetchMethod) { var _this = _super.call(this) // dummy || this; // prepare for super.init if (typeof settings === 'string') { settings = { baseUrl: settings, type: 'jwt', }; } else { settings.type = 'jwt'; } settings = new AuthenticationSettings(settings); auth = auth || new AuthToken(); _super.prototype.init.call(_this, settings, auth, fetchMethod); // Set own this props if (settings.token) { // this.auth.authenticationToken = settings.token; var token_1 = settings.token; _this.auth.tokenResolver = function () { return token_1; }; settings.token = undefined; _this.setupRefresh(); } else if (settings.enabled) { // We authenticate immediately in order to have the token in place when the first calls come in. _this.update(null); } return _this; } /** * Call the service, but take into account deferredUpdates. * * @param query The query object to create the fetch for. * @param delay A delay for when to execute the update, in milliseconds. Defaults to undefined. */ JwtAuthentication.prototype.update = function (query, delay) { var _this = this; if (this.deferUpdate) { // Save the query, so that when the deferUpdate is again false we can then execute it. this.deferredQuery = query; } else { // In case this action is triggered when a delayed execution is already pending, clear that pending timeout. clearTimeout(this.delay); if (delay > 0) { // Set up the delay this.delay = setTimeout(function () { var fetchPromise = _this.fetch(query); if (fetchPromise) { fetchPromise.catch(function (error) { return Promise.resolve(null); }); } }, delay); } else { var fetchPromise = this.fetch(query); if (fetchPromise) { fetchPromise.catch(function (error) { return Promise.resolve(null); }); } } } }; /** * Fetches the authentication-token from the server. * @param query - For the Authentication service this parameter is ignored. * @param suppressCallbacks - Set to true if you have defined callbacks, but somehow don't want them to be called. * @returns a promise that when resolved returns a jwt token. */ JwtAuthentication.prototype.fetchInternal = function (query, suppressCallbacks) { if (query === void 0) { query = new Query(); } if (suppressCallbacks === void 0) { suppressCallbacks = false; } return __awaiter(this, void 0, void 0, function () { var reqInit, err, response, data_1, _i, _a, i, error_1; return __generator(this, function (_b) { switch (_b.label) { case 0: reqInit = this.requestObject(false); _b.label = 1; case 1: _b.trys.push([1, 4, , 5]); if (!this.cbRequest(suppressCallbacks, this.settings.url, reqInit)) { err = new Error(); err.name = 'cbRequestCancelled'; throw err; } return [4 /*yield*/, this.fetchMethod(this.settings.url, reqInit)]; case 2: response = _b.sent(); if (!response.ok) { throw Error(response.status + " " + response.statusText + " for request url '" + this.settings.url + "'"); } return [4 /*yield*/, response.json() // Find the auth token by using the settings for where it is in the structure. ]; case 3: data_1 = _b.sent(); // Find the auth token by using the settings for where it is in the structure. for (_i = 0, _a = this.settings.tokenPath; _i < _a.length; _i++) { i = _a[_i]; data_1 = data_1[i]; } // Update the token this.auth.tokenResolver = function () { return data_1; }; // Set up a timer for refreshing the token before/if it expires. this.setupRefresh(); this.cbSuccess(suppressCallbacks, this.auth.authenticationToken, this.settings.url, reqInit); return [2 /*return*/, this.auth.authenticationToken]; case 4: error_1 = _b.sent(); if (error_1.name !== 'AbortError') { this.cbError(suppressCallbacks, error_1, this.settings.url, reqInit); } throw error_1; case 5: return [2 /*return*/]; } }); }); }; JwtAuthentication.prototype.setupRefresh = function () { var _this = this; try { if (this.auth && this.auth.authenticationToken) { var token = jwt.decode(this.auth.authenticationToken, null, true); var expiration = token.exp ? new Date(token.exp * 1000) : undefined; if (expiration) { var remainingSeconds = (expiration.valueOf() - new Date().valueOf()) / 1000; remainingSeconds = Math.max(remainingSeconds - this.settings.triggers.expiryOverlap, 0); // console.log( // `Setting up JWT-token to refresh in ${remainingSeconds} seconds, at ${expiration}.`, // "Token:", // token // ); setTimeout(function () { _this.update(null); }, remainingSeconds * 1000); } else { // console.log( // "The received JWT token does not expire.", // "Token:", // token // ); } } } catch (e) { console.error("Unable to parse the provided token '" + this.auth.authenticationToken + "': " + e); } }; return JwtAuthentication; }(BaseCall)); export { JwtAuthentication }; //# sourceMappingURL=JwtAuthentication.js.map