UNPKG

@mornya/auth-libs

Version:

The project of JWT / JSON Authentication process library

299 lines (298 loc) 11.7 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { EventableStorage } from '@mornya/eventable-storage-libs'; import { jwtDecode, InvalidTokenError } from 'jwt-decode'; var defaultOption = { type: 'JWT', storageTokenName: 'accessToken', isProvidedFromPostMessage: true, isShowLog: true, expiredName: 'exp', expiredIn: -1, notifyExpiredInHour: 24, isInvokeExpiredEvent: true, initialState: {}, onReceiveMessage: function () { }, onAcquiredToken: function () { return log(['ERR', 'black', 'red'], '"onAcquiredToken" function must be implemented!'); }, onExpiredToken: function () { return log(['ERR', 'black', 'red'], '"onExpiredToken" function must be implemented!'); }, onDroppedToken: function () { return log(['ERR', 'black', 'red'], '"onDroppedToken" function must be implemented!'); }, onInvalidToken: function () { return log(['ERR', 'black', 'red'], '"onInvalidToken" function must be implemented!'); }, }; var defaultResult = { statusCode: 'EMPTY', parsedToken: null, accessToken: '', expiredIn: -1, restSecond: 0, isInitialTime: false, }; var authState; var option; var expiredTID = null; var isInitialTime = true; export function initialize(authOption) { var _a; if (!window.localStorage) { log(['ERR', 'black', 'red'], 'Unable to use local storage because we didn\'t detect the object in window context.'); return false; } var initialState = authOption.initialState, restOption = __rest(authOption, ["initialState"]); option = __assign(__assign({}, defaultOption), restOption); authState = __assign({}, initialState); EventableStorage.initialize(); window.addEventListener('eventableStorage', storageEventHandler, false); if (option.isProvidedFromPostMessage) { window.addEventListener('message', messageEventHandler, false); } resolveToken((_a = window.localStorage.getItem(option.storageTokenName)) !== null && _a !== void 0 ? _a : ''); isInitialTime = false; return true; } export function destroy() { authState = undefined; clearExpiredTimeout(); window.removeEventListener('eventableStorage', storageEventHandler); if (option.isProvidedFromPostMessage) { window.removeEventListener('message', messageEventHandler); } } export function saveToken(key, value, expiredIn) { setToken(key, value, expiredIn, true); } function getState() { return authState; } function setState(nextState) { authState = __assign(__assign({}, authState), nextState); } function setToken(key, value, expiredIn, isEventable) { var expiredInLength = String(expiredIn).length; var expDate; if (expiredInLength >= 13) { expDate = expiredIn; } else if (expiredInLength === 10) { expDate = new Date(expiredIn * 1000).getTime(); } else { expDate = Date.now() + expiredIn * 1000; } if (isEventable) { window.localStorage.setItem(key, value, new Date(expDate)); } else { window.localStorage.setItemNative(key, value); window.localStorage.setExpire(key, new Date(expDate), false); } } export function checkTokenStatus(token) { var _a; if (token === void 0) { token = ''; } var result = __assign(__assign({}, defaultResult), { accessToken: token !== null && token !== void 0 ? token : '', isInitialTime: isInitialTime }); if (token) { if (option.type === 'JWT') { try { result.parsedToken = jwtDecode(token); } catch (error) { log(['AUTH', 'black', 'orange'], 'No JWT/JWE provided.'); if (error instanceof InvalidTokenError) { console.error(error.message); } result.statusCode = 'NOT_JWT'; return result; } } else if (option.type === 'JSON') { try { result.parsedToken = token.startsWith('{') && token.endsWith('}') ? JSON.parse(token) : token; } catch (error) { log(['AUTH', 'black', 'orange'], 'No JSON/Serialized provided.'); result.statusCode = 'NOT_JSON'; return result; } } else { result.statusCode = 'NOT_ANY'; return result; } var expiredIn = Number((_a = (result.parsedToken && option.expiredName && result.parsedToken[option.expiredName])) !== null && _a !== void 0 ? _a : option.expiredIn); if (expiredIn > 0) { var expiredInLength = String(expiredIn).length; var isExpired = void 0; result.expiredIn = expiredIn; result.restSecond = 1; if (expiredInLength >= 13) { var currentDate = Date.now(); isExpired = currentDate > expiredIn; result.restSecond += Math.round((expiredIn - currentDate) / 1000); } else if (expiredInLength === 10) { var currentDate = Math.floor(Date.now() / 1000); isExpired = currentDate > expiredIn; result.restSecond += expiredIn - currentDate; } else { isExpired = expiredIn <= 0; result.restSecond += expiredIn; } if (result.restSecond < 0) { result.restSecond = 0; } result.statusCode = isExpired ? 'EXPIRED' : 'SUCCEED'; } else { result.statusCode = 'EXPIRED'; } } else { result.statusCode = 'EMPTY'; } return result; } export function resolveToken(token) { if (token === void 0) { token = ''; } var result = checkTokenStatus(token !== null && token !== void 0 ? token : ''); switch (result.statusCode) { case 'SUCCEED': if (option.notifyExpiredInHour && option.notifyExpiredInHour > 0) { var restHour = Math.floor(result.restSecond / 3600); if (restHour <= option.notifyExpiredInHour) { if (restHour >= 1) { log(['AUTH', 'black', 'gold'], "Access Token will be expired in ".concat(restHour, " hour").concat(restHour > 1 ? 's' : '', ".")); } else { var restMinute = Math.ceil(result.restSecond / 60) + 1; log(['AUTH', 'black', 'gold'], "Access Token will be expired in ".concat(restMinute, " minute").concat(restMinute > 1 ? 's' : '', ".")); } } } if (option.isInvokeExpiredEvent) { clearExpiredTimeout(); expiredTID = setTimeout(function () { var nextResult = __assign(__assign({}, result), { statusCode: 'EXPIRED' }); processExpired(nextResult); }, result.restSecond * 1000); } processSucceed(result); break; case 'EXPIRED': processExpired(result); break; case 'EMPTY': processEmpty(result); break; default: processInvalid(result); break; } } function clearExpiredTimeout() { if (expiredTID) { clearTimeout(expiredTID); expiredTID = null; } } function processSucceed(result) { log(['AUTH', 'white', 'green'], 'Access Token was successfully acquired.'); if (!window.localStorage.getItem(option.storageTokenName)) { setToken(option.storageTokenName, result.accessToken, result.expiredIn, false); } option.onAcquiredToken({ result: result, getState: getState, setState: setState }); } function processExpired(result) { log(['AUTH', 'black', 'gold'], 'Access Token was expired.'); clearExpiredTimeout(); window.localStorage.removeItemNative(option.storageTokenName); window.localStorage.removeItemNative("".concat(option.storageTokenName, ".exp")); option.onExpiredToken({ result: result, next: resolveToken, getState: getState, setState: setState }); } function processInvalid(result) { clearExpiredTimeout(); option.onInvalidToken({ result: result, next: resolveToken, getState: getState, setState: setState }); } function processEmpty(result) { clearExpiredTimeout(); window.localStorage.removeItemNative(option.storageTokenName); window.localStorage.removeItemNative("".concat(option.storageTokenName, ".exp")); option.onDroppedToken({ result: result, next: resolveToken, getState: getState, setState: setState }); } function storageEventHandler(event) { if (event.detail.key === option.storageTokenName) { switch (event.detail.action) { case 'remove': case 'clear': option.onDroppedToken({ result: __assign({}, defaultResult), next: resolveToken, getState: getState, setState: setState }); break; case 'set': resolveToken(event.detail.value); break; default: break; } } } function messageEventHandler(event) { if ((event === null || event === void 0 ? void 0 : event.data) && !!option.onReceiveMessage) { option.onReceiveMessage({ event: event, next: resolveToken, getState: getState, setState: setState }); } } function getTag(tagName, color, bgColor) { var padding = tagName.length === 3 ? '3px 10px 2px 9px' : '3px 6px 2px'; return [ "%c".concat(tagName), "color:".concat(color, ";background-color:").concat(bgColor, ";border-radius:4px;line-height:1;padding:").concat(padding), ]; } function log(tags, message) { if (option.isShowLog) { var _a = __read(tags, 3), tagName = _a[0], color = _a[1], bgColor = _a[2]; console.info.apply(console, __spreadArray(__spreadArray([], __read(getTag(tagName, color, bgColor)), false), [message], false)); } }