@mornya/auth-libs
Version:
The project of JWT / JSON Authentication process library
299 lines (298 loc) • 11.7 kB
JavaScript
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));
}
}