UNPKG

box-node-sdk

Version:

Official SDK for Box Plaform APIs

182 lines 8.64 kB
"use strict"; /** * @fileoverview App Auth Box API Session. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; // ------------------------------------------------------------------------------ // Requirements // ------------------------------------------------------------------------------ var assert_1 = __importDefault(require("assert")); var bluebird_1 = require("bluebird"); var errors_1 = __importDefault(require("../util/errors")); // ------------------------------------------------------------------------------ // Private // ------------------------------------------------------------------------------ /** * Validate that an object is a valid TokenStore object * * @param {Object} obj the object to validate * @returns {boolean} returns true if the passed in object is a valid TokenStore object that * has all the expected properties. false otherwise. * @private */ function isObjectValidTokenStore(obj) { return Boolean(obj && obj.read && obj.write && obj.clear); } // ------------------------------------------------------------------------------ // Public // ------------------------------------------------------------------------------ /** * App Auth Box API Session. * * The App Auth API Session holds an accessToken for an app user or enterprise, * which it returns to the client so that it may make calls on behalf of * these entities. * * These access tokens will be refreshed in the background if a request is made within the * "stale buffer" (defaults to 10 minutes before the token is set to expire). * If the token is also expired, all incoming requests will be held until a fresh token * is retrieved. * * @param {string} type The type of the entity to authenticate the app auth session as, "user" or "enterprise" * @param {string} id The Box ID of the entity to authenticate as * @param {Config} config The SDK configuration options * @param {TokenManager} tokenManager The TokenManager * @param {TokenStore} [tokenStore] The token store instance to use for caching token info * @constructor */ var AppAuthSession = /** @class */ (function () { function AppAuthSession(type, id, config, tokenManager, tokenStore) { this._type = type; this._id = id; this._config = config; this._tokenManager = tokenManager; // If tokenStore was provided, set the persistent data & current store operations if (tokenStore) { (0, assert_1.default)(isObjectValidTokenStore(tokenStore), 'Token store provided is improperly formatted. Methods required: read(), write(), clear().'); this._tokenStore = bluebird_1.Promise.promisifyAll(tokenStore); } // The TokenInfo object for this app auth session this._tokenInfo = null; // Indicates if tokens are currently being refreshed this._refreshPromise = null; } /** * Initiate a refresh of the app auth access tokens. New tokens should be passed * to the caller, and then cached for later use. * * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant * @returns {Promise<string>} Promise resolving to the access token * @private */ AppAuthSession.prototype._refreshAppAuthAccessToken = function (options) { var _this = this; // If tokens aren't already being refreshed, start the refresh if (!this._refreshPromise) { this._refreshPromise = this._tokenManager .getTokensJWTGrant(this._type, this._id, options) .then(function (tokenInfo) { // Set new token info and propagate the new access token _this._tokenInfo = tokenInfo; if (_this._tokenStore) { return _this._tokenStore .writeAsync(tokenInfo) .then(function () { return tokenInfo.accessToken; }); } return tokenInfo.accessToken; }) .finally(function () { // Refresh complete, clear promise _this._refreshPromise = null; }); } return this._refreshPromise; }; /** * Produces a valid, app auth access token. * Performs a refresh before returning if the current token is expired. If the current * token is considered stale but still valid, return the current token but initiate a * new refresh in the background. * * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant * @returns {Promise<string>} Promise resolving to the access token */ AppAuthSession.prototype.getAccessToken = function (options) { var _this = this; var expirationBuffer = this._config.expiredBufferMS; // If we're initializing the client and have a token store, try reading from it if (!this._tokenInfo && this._tokenStore) { return this._tokenStore.readAsync().then(function (tokenInfo) { if (!_this._tokenManager.isAccessTokenValid(tokenInfo, expirationBuffer)) { // Token store contains expired tokens, refresh return _this._refreshAppAuthAccessToken(options); } _this._tokenInfo = tokenInfo; return tokenInfo.accessToken; }); } // If the current token is not fresh, get a new token. All incoming // requests will be held until a fresh token is retrieved. if (!this._tokenInfo || !this._tokenManager.isAccessTokenValid(this._tokenInfo, expirationBuffer)) { return this._refreshAppAuthAccessToken(options); } // Your token is not currently stale! Return the current access token. return bluebird_1.Promise.resolve(this._tokenInfo.accessToken); }; /** * Revokes the app auth token used by this session, and clears the saved tokenInfo. * * @param {TokenRequestOptions} [options]- Sets optional behavior for the token grant * @returns {Promise} Promise resolving if the revoke succeeds */ AppAuthSession.prototype.revokeTokens = function (options) { // The current app auth token is revoked (but a new one will be created automatically as needed). var tokenInfo = this._tokenInfo || {}, accessToken = tokenInfo.accessToken; this._tokenInfo = null; return this._tokenManager.revokeTokens(accessToken, options); }; /** * Exchange the client access token for one with lower scope * @param {string|string[]} scopes The scope(s) requested for the new token * @param {string} [resource] The absolute URL of an API resource to scope the new token to * @param {Object} [options] - Optional parameters * @param {TokenRequestOptions} [options.tokenRequestOptions] - Sets optional behavior for the token grant * @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens * @returns {Promise<TokenInfo>} Promise resolving to the new token info */ AppAuthSession.prototype.exchangeToken = function (scopes, resource, options) { var _this = this; return this.getAccessToken(options).then(function (accessToken) { return _this._tokenManager.exchangeToken(accessToken, scopes, resource, options); }); }; /** * Handle an an "Expired Tokens" Error. If our tokens are expired, we need to clear the token * store (if present) before continuing. * * @param {Errors~ExpiredTokensError} err An "expired tokens" error including information * about the request/response. * @returns {Promise<Error>} Promise resolving to an error. This will * usually be the original response error, but could an error from trying to access the * token store as well. */ AppAuthSession.prototype.handleExpiredTokensError = function (err /* FIXME */) { if (!this._tokenStore) { return bluebird_1.Promise.resolve(err); } // If a token store is available, clear the store and throw either error // eslint-disable-next-line promise/no-promise-in-callback return this._tokenStore .clearAsync() .catch(function (e) { return errors_1.default.unwrapAndThrow(e); }) .then(function () { throw err; }); }; return AppAuthSession; }()); module.exports = AppAuthSession; //# sourceMappingURL=app-auth-session.js.map