diff --git a/src/redux/middleware/authMiddleware.js b/src/redux/middleware/authMiddleware.js index f6d9e668d..9cbb20f1a 100644 --- a/src/redux/middleware/authMiddleware.js +++ b/src/redux/middleware/authMiddleware.js @@ -8,6 +8,7 @@ import { setLang } from '../modules/app.js'; import { CALL_API } from './apiMiddleware.js'; import { safeGet, canUseDOM } from '../../helpers/common.js'; import { getConfigVar } from '../../helpers/config.js'; +import { decode, isTokenValid } from '../helpers/token'; const PERSISTENT_TOKENS_KEY_PREFIX = getConfigVar('PERSISTENT_TOKENS_KEY_PREFIX') || 'recodex'; @@ -26,8 +27,13 @@ export const storeToken = accessToken => { localStorage.setItem(TOKEN_LOCAL_STORAGE_KEY, accessToken); } - // @todo: expire after 'exp' in the token - cookies.set(TOKEN_COOKIES_KEY, accessToken, { expires: 14 }); // expires after 14 days + const decodedToken = decode(accessToken); + if (decodedToken && isTokenValid(decodedToken)) { + const expDate = new Date(decodedToken.exp * 1000); + cookies.set(TOKEN_COOKIES_KEY, accessToken, { expires: expDate }); // expires with token expiration + } else { + cookies.erase(TOKEN_COOKIES_KEY); + } } }; @@ -67,6 +73,19 @@ export const getToken = () => { return null; }; +const checkAccessTokenCookie = token => { + const cookieToken = cookies.get(TOKEN_COOKIES_KEY); + const decodedCookieToken = cookieToken && decode(cookieToken); + if (!decodedCookieToken || !isTokenValid(decodedCookieToken)) { + const decodedToken = token && decode(token); + if (decodedToken && isTokenValid(decodedToken)) { + storeToken(token); + } else { + removeToken(); + } + } +}; + /** * Store instance ID to both local storage and cookies. */ @@ -155,6 +174,8 @@ const middleware = store => next => action => { } } + checkAccessTokenCookie(action.request.accessToken); + break; } diff --git a/src/redux/modules/auth.js b/src/redux/modules/auth.js index b6ea61a1f..3f1c1b9e1 100644 --- a/src/redux/modules/auth.js +++ b/src/redux/modules/auth.js @@ -139,8 +139,8 @@ export const selectInstance = createAction(actionTypes.SELECT_INSTANCE, instance /** * Authentication reducer. - * @param {string} accessToken An access token to initialise the reducer - * @return {function} The initialised reducer + * @param {string} accessToken An access token to initialize the reducer + * @return {function} The initialized reducer */ const auth = (accessToken, instanceId, now = Date.now()) => { const decodedToken = decodeAndValidateAccessToken(accessToken, now); @@ -168,7 +168,7 @@ const auth = (accessToken, instanceId, now = Date.now()) => { [actionTypes.LOGIN_FULFILLED]: (state, { payload: { accessToken, user }, meta: { service, popupWindow } }) => { closeAuthPopupWindow(popupWindow); - return state.getIn(['status', service]) === statusTypes.LOGGING_IN // this should prevent re-login, when explicit logout ocurred whilst refreshing token + return state.getIn(['status', service]) === statusTypes.LOGGING_IN // this should prevent re-login, when explicit logout occurred whilst refreshing token ? state .setIn(['status', service], statusTypes.LOGGED_IN) .deleteIn(['errors', service])