UNPKG

redux-refresh-token

Version:

A promise callback to refresh access tokens when using RSAA

129 lines (108 loc) 4.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createFSAConverter = undefined; exports.default = attemptRefresh; var _actions = require("./actions"); function attemptRefresh(settings) { var action = settings.action, failure = settings.failure, _settings$isRefreshCa = settings.isRefreshCall, isRefreshCall = _settings$isRefreshCa === undefined ? defaultIsRefreshCall : _settings$isRefreshCa, next = settings.next, refreshActionCreator = settings.refreshActionCreator, _settings$refreshRedu = settings.refreshReducerKey, refreshReducerKey = _settings$refreshRedu === undefined ? "tokenRefresh" : _settings$refreshRedu, _settings$setAccessTo = settings.setAccessTokenActionCreator, setAccessTokenActionCreator = _settings$setAccessTo === undefined ? _actions.setAccessToken : _settings$setAccessTo, store = settings.store, token = settings.token; return function (response) { // The API call returned unauthorized user (access token is expired) if (response.error && response.payload.status === 401 && // The refresh endpoint might return 401, so we skip the check here // otherwise we get stuck in an infinite loop !isRefreshCall(action, refreshActionCreator()) && // We should not run the refresh flow when no token was given to begin with // (for instance Forgot Password, Login etc.) typeof token === "string" && token.length > 0) { // This will ensure that the fail action goes all the way to the bottom next(response); // We check if there is already dispatched a call to refresh the token, // if so we can simply queue the call until the refresh request completes var refreshPromise = store.getState()[refreshReducerKey].refreshTokenPromise; if (!refreshPromise) { refreshPromise = requestNewAccessToken({ store: store, next: next, setAccessTokenActionCreator: setAccessTokenActionCreator, refreshActionCreator: refreshActionCreator }); next((0, _actions.saveRefreshTokenPromise)(refreshPromise)); } // When the refresh attempt is done, we fire all the actions that have been queued until // its completion. If, the refresh promise was unsuccessful we logout the user. return refreshPromise.then(function (response) { if (!response.error) { return store.dispatch(action); } return store.dispatch(failure()) // Ensure subscribers do not get an empty response, e.g. T512 .then(function (response) { return { error: true }; }); }); } return next(response); }; } var requestNewAccessToken = function requestNewAccessToken(_ref) { var store = _ref.store, next = _ref.next, setAccessTokenActionCreator = _ref.setAccessTokenActionCreator, refreshActionCreator = _ref.refreshActionCreator; return store.dispatch(refreshActionCreator()).then(function (response) { // Refresh was successful next((0, _actions.clearRefreshTokenPromise)()); // Refresh was successful if (!response.error) { next(setAccessTokenActionCreator(response.payload)); return { error: false }; } return { error: true }; }); }; var defaultIsRefreshCall = function defaultIsRefreshCall(action, refreshAction) { return action["Call API"].endpoint === refreshAction["Call API"].endpoint; }; var createFSAConverter = exports.createFSAConverter = function createFSAConverter(successType, failureType) { return function (response) { if (!response.ok) { return { error: true, payload: { status: response.status }, type: failureType }; } var contentType = response.headers.get("Content-Type"); var emptyCodes = [204, 205]; var createSuccessType = function createSuccessType(payload) { return { payload: payload, type: successType }; }; if (emptyCodes.indexOf(response.status) === -1 && contentType && contentType.indexOf("json") !== -1) { return response.json().then(createSuccessType); } else { return createSuccessType(); } }; };