Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

axios-jwt

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

axios-jwt - npm Package Compare versions

Comparing version 3.0.2 to 4.0.0

147

dist/src/authTokenInterceptor.js

@@ -55,25 +55,4 @@ "use strict";

var expireFudge = 10;
var isRefreshing = false;
var queue = [];
var currentlyRequestingPromise = undefined;
/**
* Function that resolves all items in the queue with the provided token
* @param token New access token
*/
var resolveQueue = function (token) {
queue.forEach(function (p) {
p.resolve(token);
});
queue = [];
};
/**
* Function that declines all items in the queue with the provided error
* @param error Error
*/
var declineQueue = function (error) {
queue.forEach(function (p) {
p.reject(error);
});
queue = [];
};
/**
* Gets the unix timestamp from an access token

@@ -114,2 +93,3 @@ *

* Refreshes the access token using the provided function
* Note: NOT to be called externally. Only accessible through an interceptor
*

@@ -124,36 +104,37 @@ * @param {requestRefresh} requestRefresh - Function that is used to get a new access token

switch (_c.label) {
case 0:
refreshToken = (0, tokensUtils_1.getRefreshToken)();
case 0: return [4 /*yield*/, (0, tokensUtils_1.getRefreshToken)()];
case 1:
refreshToken = _c.sent();
if (!refreshToken)
throw new Error('No refresh token available');
_c.label = 1;
case 1:
_c.trys.push([1, 7, 8, 9]);
isRefreshing = true;
_c.label = 2;
case 2:
_c.trys.push([2, 8, , 11]);
return [4 /*yield*/, requestRefresh(refreshToken)];
case 2:
case 3:
newTokens = _c.sent();
if (!(typeof newTokens === 'object' && (newTokens === null || newTokens === void 0 ? void 0 : newTokens.accessToken))) return [3 /*break*/, 4];
if (!(typeof newTokens === 'object' && (newTokens === null || newTokens === void 0 ? void 0 : newTokens.accessToken))) return [3 /*break*/, 5];
return [4 /*yield*/, (0, setAuthTokens_1.setAuthTokens)(newTokens)];
case 3:
case 4:
_c.sent();
return [2 /*return*/, newTokens.accessToken];
case 4:
if (!(typeof newTokens === 'string')) return [3 /*break*/, 6];
case 5:
if (!(typeof newTokens === 'string')) return [3 /*break*/, 7];
return [4 /*yield*/, (0, tokensUtils_1.setAccessToken)(newTokens)];
case 5:
case 6:
_c.sent();
return [2 /*return*/, newTokens];
case 6: throw new Error('requestRefresh must either return a string or an object with an accessToken');
case 7:
case 7: throw new Error('requestRefresh must either return a string or an object with an accessToken');
case 8:
error_1 = _c.sent();
// Failed to refresh token
if (axios_1.default.isAxiosError(error_1)) {
status_1 = (_a = error_1.response) === null || _a === void 0 ? void 0 : _a.status;
if (status_1 === 401 || status_1 === 422) {
// The refresh token is invalid so remove the stored tokens
(_b = StorageProxy_1.StorageProxy.Storage) === null || _b === void 0 ? void 0 : _b.remove(StorageKey_1.STORAGE_KEY);
throw new Error("Got ".concat(status_1, " on token refresh; clearing both auth tokens"));
}
}
if (!axios_1.default.isAxiosError(error_1)) return [3 /*break*/, 10];
status_1 = (_a = error_1.response) === null || _a === void 0 ? void 0 : _a.status;
if (!(status_1 === 401 || status_1 === 422)) return [3 /*break*/, 10];
// The refresh token is invalid so remove the stored tokens
return [4 /*yield*/, ((_b = StorageProxy_1.StorageProxy.Storage) === null || _b === void 0 ? void 0 : _b.remove(StorageKey_1.STORAGE_KEY))];
case 9:
// The refresh token is invalid so remove the stored tokens
_c.sent();
throw new Error("Got ".concat(status_1, " on token refresh; clearing both auth tokens"));
case 10:
// A different error, probably network error

@@ -166,7 +147,4 @@ if (error_1 instanceof Error) {

}
return [3 /*break*/, 9];
case 8:
isRefreshing = false;
return [7 /*endfinally*/];
case 9: return [2 /*return*/];
return [3 /*break*/, 11];
case 11: return [2 /*return*/];
}

@@ -189,11 +167,14 @@ });

switch (_a.label) {
case 0:
accessToken = (0, tokensUtils_1.getAccessToken)();
if (!(!accessToken || isTokenExpired(accessToken))) return [3 /*break*/, 2];
case 0: return [4 /*yield*/, (0, tokensUtils_1.getAccessToken)()
// check if access token is expired
];
case 1:
accessToken = _a.sent();
if (!(!accessToken || isTokenExpired(accessToken))) return [3 /*break*/, 3];
return [4 /*yield*/, refreshToken(requestRefresh)];
case 1:
case 2:
// do refresh
accessToken = _a.sent();
_a.label = 2;
case 2: return [2 /*return*/, accessToken];
_a.label = 3;
case 3: return [2 /*return*/, accessToken];
}

@@ -222,38 +203,38 @@ });

switch (_a.label) {
case 0:
case 0: return [4 /*yield*/, (0, tokensUtils_1.getRefreshToken)()];
case 1:
// Waiting for a fix in axios types
// We need refresh token to do any authenticated requests
if (!(0, tokensUtils_1.getRefreshToken)())
return [2 /*return*/, requestConfig
// Queue the request if another refresh request is currently happening
];
// Queue the request if another refresh request is currently happening
if (isRefreshing) {
return [2 /*return*/, new Promise(function (resolve, reject) {
queue.push({ resolve: resolve, reject: reject });
})
.then(function (token) {
if (requestConfig.headers) {
requestConfig.headers[header] = "".concat(headerPrefix).concat(token);
}
return requestConfig;
})
.catch(Promise.reject)];
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, (0, exports.refreshTokenIfNeeded)(requestRefresh)];
if (!(_a.sent()))
return [2 /*return*/, requestConfig];
accessToken = undefined;
if (!currentlyRequestingPromise) return [3 /*break*/, 3];
return [4 /*yield*/, currentlyRequestingPromise];
case 2:
accessToken = _a.sent();
resolveQueue(accessToken);
return [3 /*break*/, 4];
_a.label = 3;
case 3:
if (!!accessToken) return [3 /*break*/, 7];
_a.label = 4;
case 4:
_a.trys.push([4, 6, , 7]);
// Sets the promise so everyone else will wait - then get the value
currentlyRequestingPromise = (0, exports.refreshTokenIfNeeded)(requestRefresh);
return [4 /*yield*/, currentlyRequestingPromise
// Reset the promise
];
case 5:
accessToken = _a.sent();
// Reset the promise
currentlyRequestingPromise = undefined;
return [3 /*break*/, 7];
case 6:
error_2 = _a.sent();
// Reset the promise
currentlyRequestingPromise = undefined;
if (error_2 instanceof Error) {
declineQueue(error_2);
throw new Error("Unable to refresh access token for request due to token refresh error: ".concat(error_2.message));
}
return [3 /*break*/, 4];
case 4:
return [3 /*break*/, 7];
case 7:
// add token to headers

@@ -260,0 +241,0 @@ if (accessToken && requestConfig.headers) {

export declare class BrowserStorageService {
private _storage;
constructor(storage: Storage);
remove(key: string): void;
get(key: string): string | null;
set(key: string, value: string): void;
remove(key: string): Promise<void>;
get(key: string): Promise<string | null>;
set(key: string, value: string): Promise<void>;
}
//# sourceMappingURL=BrowserStorageService.d.ts.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -9,9 +45,23 @@ exports.BrowserStorageService = void 0;

BrowserStorageService.prototype.remove = function (key) {
this._storage.removeItem(key);
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
this._storage.removeItem(key);
return [2 /*return*/];
});
});
};
BrowserStorageService.prototype.get = function (key) {
return this._storage.getItem(key);
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._storage.getItem(key)];
});
});
};
BrowserStorageService.prototype.set = function (key, value) {
this._storage.setItem(key, value);
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
this._storage.setItem(key, value);
return [2 /*return*/];
});
});
};

@@ -18,0 +68,0 @@ return BrowserStorageService;

@@ -6,3 +6,3 @@ import { IAuthTokens } from './IAuthTokens';

*/
export declare const setAuthTokens: (tokens: IAuthTokens) => void;
export declare const setAuthTokens: (tokens: IAuthTokens) => Promise<void>;
//# sourceMappingURL=setAuthTokens.d.ts.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -10,4 +46,9 @@ exports.setAuthTokens = void 0;

*/
var setAuthTokens = function (tokens) { var _a; return (_a = StorageProxy_1.StorageProxy.Storage) === null || _a === void 0 ? void 0 : _a.set(StorageKey_1.STORAGE_KEY, JSON.stringify(tokens)); };
var setAuthTokens = function (tokens) { return __awaiter(void 0, void 0, void 0, function () { var _a; return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, ((_a = StorageProxy_1.StorageProxy.Storage) === null || _a === void 0 ? void 0 : _a.set(StorageKey_1.STORAGE_KEY, JSON.stringify(tokens)))];
case 1: return [2 /*return*/, _b.sent()];
}
}); }); };
exports.setAuthTokens = setAuthTokens;
//# sourceMappingURL=setAuthTokens.js.map
export type StorageType = {
remove(key: string): void;
set(key: string, value: string): void;
get(value: string): string | null;
remove(key: string): Promise<void>;
set(key: string, value: string): Promise<void>;
get(value: string): Promise<string | null>;
};
//# sourceMappingURL=StorageType.d.ts.map

@@ -6,3 +6,3 @@ import { Token } from './Token';

*/
export declare const setAccessToken: (token: Token) => void;
export declare const setAccessToken: (token: Token) => Promise<void>;
/**

@@ -12,3 +12,3 @@ * Returns the stored refresh token

*/
export declare const getRefreshToken: () => Token | undefined;
export declare const getRefreshToken: () => Promise<Token | undefined>;
/**

@@ -18,7 +18,7 @@ * Returns the stored access token

*/
export declare const getAccessToken: () => Token | undefined;
export declare const getAccessToken: () => Promise<Token | undefined>;
/**
* Clears both tokens
*/
export declare const clearAuthTokens: () => void;
export declare const clearAuthTokens: () => Promise<void>;
/**

@@ -28,3 +28,3 @@ * Checks if refresh tokens are stored

*/
export declare const isLoggedIn: () => boolean;
export declare const isLoggedIn: () => Promise<boolean>;
//# sourceMappingURL=tokensUtils.d.ts.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -12,18 +48,26 @@ exports.isLoggedIn = exports.clearAuthTokens = exports.getAccessToken = exports.getRefreshToken = exports.setAccessToken = void 0;

*/
var getAuthTokens = function () {
var getAuthTokens = function () { return __awaiter(void 0, void 0, void 0, function () {
var rawTokens;
var _a;
var rawTokens = (_a = StorageProxy_1.StorageProxy.Storage) === null || _a === void 0 ? void 0 : _a.get(StorageKey_1.STORAGE_KEY);
if (!rawTokens)
return;
try {
// parse stored tokens JSON
return JSON.parse(rawTokens);
}
catch (error) {
if (error instanceof SyntaxError) {
error.message = "Failed to parse auth tokens: ".concat(rawTokens);
throw error;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, ((_a = StorageProxy_1.StorageProxy.Storage) === null || _a === void 0 ? void 0 : _a.get(StorageKey_1.STORAGE_KEY))];
case 1:
rawTokens = _b.sent();
if (!rawTokens)
return [2 /*return*/];
try {
// parse stored tokens JSON
return [2 /*return*/, JSON.parse(rawTokens)];
}
catch (error) {
if (error instanceof SyntaxError) {
error.message = "Failed to parse auth tokens: ".concat(rawTokens);
throw error;
}
}
return [2 /*return*/];
}
}
};
});
}); };
/**

@@ -33,10 +77,20 @@ * Sets the access token

*/
var setAccessToken = function (token) {
var tokens = getAuthTokens();
if (!tokens) {
throw new Error('Unable to update access token since there are not tokens currently stored');
}
tokens.accessToken = token;
(0, setAuthTokens_1.setAuthTokens)(tokens);
};
var setAccessToken = function (token) { return __awaiter(void 0, void 0, void 0, function () {
var tokens;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getAuthTokens()];
case 1:
tokens = _a.sent();
if (!tokens) {
throw new Error('Unable to update access token since there are not tokens currently stored');
}
tokens.accessToken = token;
return [4 /*yield*/, (0, setAuthTokens_1.setAuthTokens)(tokens)];
case 2:
_a.sent();
return [2 /*return*/];
}
});
}); };
exports.setAccessToken = setAccessToken;

@@ -47,6 +101,13 @@ /**

*/
var getRefreshToken = function () {
var tokens = getAuthTokens();
return tokens ? tokens.refreshToken : undefined;
};
var getRefreshToken = function () { return __awaiter(void 0, void 0, void 0, function () {
var tokens;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getAuthTokens()];
case 1:
tokens = _a.sent();
return [2 /*return*/, tokens ? tokens.refreshToken : undefined];
}
});
}); };
exports.getRefreshToken = getRefreshToken;

@@ -57,6 +118,13 @@ /**

*/
var getAccessToken = function () {
var tokens = getAuthTokens();
return tokens ? tokens.accessToken : undefined;
};
var getAccessToken = function () { return __awaiter(void 0, void 0, void 0, function () {
var tokens;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getAuthTokens()];
case 1:
tokens = _a.sent();
return [2 /*return*/, tokens ? tokens.accessToken : undefined];
}
});
}); };
exports.getAccessToken = getAccessToken;

@@ -66,3 +134,18 @@ /**

*/
var clearAuthTokens = function () { var _a; return (_a = StorageProxy_1.StorageProxy.Storage) === null || _a === void 0 ? void 0 : _a.remove(StorageKey_1.STORAGE_KEY); };
var clearAuthTokens = function () { return __awaiter(void 0, void 0, void 0, function () { var _a; return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, ((_a = StorageProxy_1.StorageProxy.Storage) === null || _a === void 0 ? void 0 : _a.remove(StorageKey_1.STORAGE_KEY))
/**
* Checks if refresh tokens are stored
* @returns Whether the user is logged in or not
*/
];
case 1: return [2 /*return*/, _b.sent()
/**
* Checks if refresh tokens are stored
* @returns Whether the user is logged in or not
*/
];
}
}); }); };
exports.clearAuthTokens = clearAuthTokens;

@@ -73,7 +156,14 @@ /**

*/
var isLoggedIn = function () {
var token = (0, exports.getRefreshToken)();
return !!token;
};
var isLoggedIn = function () { return __awaiter(void 0, void 0, void 0, function () {
var token;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, exports.getRefreshToken)()];
case 1:
token = _a.sent();
return [2 /*return*/, !!token];
}
});
}); };
exports.isLoggedIn = isLoggedIn;
//# sourceMappingURL=tokensUtils.js.map
{
"name": "axios-jwt",
"version": "3.0.2",
"version": "4.0.0",
"description": "Axios interceptor to store, use, and refresh tokens for authentication.",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -149,3 +149,3 @@ # axios-jwt

return axios.post(`${BASE_URL}/auth/refresh_token`, { refresh })
.then(response => resolve(response.data.access_token))
.then(response => response.data.access_token)
};

@@ -152,0 +152,0 @@

@@ -18,35 +18,5 @@ import { getAccessToken, getRefreshToken, setAccessToken } from './tokensUtils'

type RequestsQueue = {
resolve: (value?: unknown) => void
reject: (reason?: unknown) => void
}[]
let currentlyRequestingPromise: Promise<Token | undefined> | undefined = undefined
let isRefreshing = false
let queue: RequestsQueue = []
/**
* Function that resolves all items in the queue with the provided token
* @param token New access token
*/
const resolveQueue = (token?: Token) => {
queue.forEach((p) => {
p.resolve(token)
})
queue = []
}
/**
* Function that declines all items in the queue with the provided error
* @param error Error
*/
const declineQueue = (error: Error) => {
queue.forEach((p) => {
p.reject(error)
})
queue = []
}
/**
* Gets the unix timestamp from an access token

@@ -91,2 +61,3 @@ *

* Refreshes the access token using the provided function
* Note: NOT to be called externally. Only accessible through an interceptor
*

@@ -97,8 +68,6 @@ * @param {requestRefresh} requestRefresh - Function that is used to get a new access token

const refreshToken = async (requestRefresh: TokenRefreshRequest): Promise<Token> => {
const refreshToken = getRefreshToken()
const refreshToken = await getRefreshToken()
if (!refreshToken) throw new Error('No refresh token available')
try {
isRefreshing = true
// Refresh and store access token using the supplied refresh function

@@ -121,3 +90,3 @@ const newTokens = await requestRefresh(refreshToken)

// The refresh token is invalid so remove the stored tokens
StorageProxy.Storage?.remove(STORAGE_KEY)
await StorageProxy.Storage?.remove(STORAGE_KEY)
throw new Error(`Got ${status} on token refresh; clearing both auth tokens`)

@@ -133,4 +102,2 @@ }

}
} finally {
isRefreshing = false
}

@@ -154,3 +121,3 @@ }

// use access token (if we have it)
let accessToken = getAccessToken()
let accessToken = await getAccessToken()

@@ -160,3 +127,2 @@ // check if access token is expired

// do refresh
accessToken = await refreshToken(requestRefresh)

@@ -192,29 +158,26 @@ }

// We need refresh token to do any authenticated requests
if (!getRefreshToken()) return requestConfig
if (!(await getRefreshToken())) return requestConfig
// Queue the request if another refresh request is currently happening
if (isRefreshing) {
return new Promise((resolve, reject) => {
queue.push({ resolve, reject })
})
.then((token) => {
if (requestConfig.headers) {
requestConfig.headers[header] = `${headerPrefix}${token}`
}
return requestConfig
})
.catch(Promise.reject)
}
let accessToken = undefined
// Do refresh if needed
let accessToken
try {
accessToken = await refreshTokenIfNeeded(requestRefresh)
resolveQueue(accessToken)
} catch (error: unknown) {
if (error instanceof Error) {
declineQueue(error)
throw new Error(
`Unable to refresh access token for request due to token refresh error: ${error.message}`
)
// Try to await a current request
if (currentlyRequestingPromise) accessToken = await currentlyRequestingPromise
if (!accessToken) {
try {
// Sets the promise so everyone else will wait - then get the value
currentlyRequestingPromise = refreshTokenIfNeeded(requestRefresh)
accessToken = await currentlyRequestingPromise
// Reset the promise
currentlyRequestingPromise = undefined
} catch (error: unknown) {
// Reset the promise
currentlyRequestingPromise = undefined
if (error instanceof Error) {
throw new Error(
`Unable to refresh access token for request due to token refresh error: ${error.message}`
)
}
}

@@ -221,0 +184,0 @@ }

@@ -8,13 +8,13 @@ export class BrowserStorageService {

remove(key: string) {
async remove(key: string) {
this._storage.removeItem(key)
}
get(key: string) {
async get(key: string) {
return this._storage.getItem(key)
}
set(key: string, value: string) {
async set(key: string, value: string) {
this._storage.setItem(key, value)
}
}

@@ -9,3 +9,3 @@ import { StorageProxy } from './StorageProxy'

*/
export const setAuthTokens = (tokens: IAuthTokens): void =>
StorageProxy.Storage?.set(STORAGE_KEY, JSON.stringify(tokens))
export const setAuthTokens = async (tokens: IAuthTokens): Promise<void> =>
await StorageProxy.Storage?.set(STORAGE_KEY, JSON.stringify(tokens))
export type StorageType = {
remove(key: string): void
set(key: string, value: string): void
get(value: string): string | null
remove(key: string): Promise<void>
set(key: string, value: string): Promise<void>
get(value: string): Promise<string | null>
}

@@ -13,4 +13,4 @@ import { setAuthTokens } from './setAuthTokens'

*/
const getAuthTokens = (): IAuthTokens | undefined => {
const rawTokens = StorageProxy.Storage?.get(STORAGE_KEY)
const getAuthTokens = async (): Promise<IAuthTokens | undefined> => {
const rawTokens = await StorageProxy.Storage?.get(STORAGE_KEY)
if (!rawTokens) return

@@ -33,4 +33,4 @@

*/
export const setAccessToken = (token: Token): void => {
const tokens = getAuthTokens()
export const setAccessToken = async (token: Token): Promise<void> => {
const tokens = await getAuthTokens()
if (!tokens) {

@@ -41,3 +41,3 @@ throw new Error('Unable to update access token since there are not tokens currently stored')

tokens.accessToken = token
setAuthTokens(tokens)
await setAuthTokens(tokens)
}

@@ -49,4 +49,4 @@

*/
export const getRefreshToken = (): Token | undefined => {
const tokens = getAuthTokens()
export const getRefreshToken = async (): Promise<Token | undefined> => {
const tokens = await getAuthTokens()
return tokens ? tokens.refreshToken : undefined

@@ -59,4 +59,4 @@ }

*/
export const getAccessToken = (): Token | undefined => {
const tokens = getAuthTokens()
export const getAccessToken = async (): Promise<Token | undefined> => {
const tokens = await getAuthTokens()
return tokens ? tokens.accessToken : undefined

@@ -68,3 +68,4 @@ }

*/
export const clearAuthTokens = (): void => StorageProxy.Storage?.remove(STORAGE_KEY)
export const clearAuthTokens = async (): Promise<void> =>
await StorageProxy.Storage?.remove(STORAGE_KEY)

@@ -75,5 +76,5 @@ /**

*/
export const isLoggedIn = (): boolean => {
const token = getRefreshToken()
export const isLoggedIn = async (): Promise<boolean> => {
const token = await getRefreshToken()
return !!token
}

@@ -1,4 +0,4 @@

import { AxiosRequestConfig } from 'axios';
import jwt from 'jsonwebtoken';
import { authTokenInterceptor } from '../index';
import { AxiosRequestConfig } from 'axios'
import jwt from 'jsonwebtoken'
import { authTokenInterceptor } from '../index'

@@ -5,0 +5,0 @@ describe('authTokenInterceptor', () => {

@@ -1,7 +0,6 @@

import { STORAGE_KEY } from '../src/StorageKey';
import { clearAuthTokens } from '../index';
import { STORAGE_KEY } from '../src/StorageKey'
import { clearAuthTokens } from '../index'
describe('clearAuthTokens', () => {
it('removes the tokens from localstorage', () => {
it('removes the tokens from localstorage', async () => {
// GIVEN

@@ -14,3 +13,3 @@ // Tokens are stored in localStorage

// I call clearAuthTokens
clearAuthTokens()
await clearAuthTokens()

@@ -17,0 +16,0 @@ // THEN

@@ -1,3 +0,3 @@

import { getAccessToken, authTokenInterceptor, getBrowserSessionStorage } from '../index';
import { STORAGE_KEY } from '../src/StorageKey';
import { getAccessToken, authTokenInterceptor, getBrowserSessionStorage } from '../index'
import { STORAGE_KEY } from '../src/StorageKey'

@@ -11,3 +11,3 @@ describe('getAccessToken', () => {

describe('for localStorage', function () {
it('returns undefined if tokens are not set', () => {
it('returns undefined if tokens are not set', async () => {
// GIVEN

@@ -19,3 +19,3 @@ // localStorage is empty

// I call getAccessToken
const result = getAccessToken()
const result = await getAccessToken()

@@ -27,3 +27,3 @@ // THEN

it('returns the access token is it is set', () => {
it('returns the access token is it is set', async () => {
// GIVEN

@@ -36,3 +36,3 @@ // Both tokens are stored in localstorage

// I call getAccessToken
const result = getAccessToken()
const result = await getAccessToken()

@@ -43,13 +43,13 @@ // THEN

})
});
})
describe('for sessionStorage', function () {
beforeEach( () => {
beforeEach(() => {
const getStorage = getBrowserSessionStorage
const requestRefresh = jest.fn()
authTokenInterceptor({getStorage, requestRefresh })
authTokenInterceptor({ getStorage, requestRefresh })
})
it('returns undefined if tokens are not set', () => {
it('returns undefined if tokens are not set', async () => {
// GIVEN

@@ -61,3 +61,3 @@ // localStorage is empty

// I call getAccessToken
const result = getAccessToken()
const result = await getAccessToken()

@@ -69,3 +69,3 @@ // THEN

it('returns the access token is it is set', () => {
it('returns the access token is it is set', async () => {
// GIVEN

@@ -78,3 +78,3 @@ // Both tokens are stored in localstorage

// I call getAccessToken
const result = getAccessToken()
const result = await getAccessToken()

@@ -81,0 +81,0 @@ // THEN

@@ -1,6 +0,6 @@

import { getRefreshToken } from '../index';
import { STORAGE_KEY } from '../src/StorageKey';
import { getRefreshToken } from '../index'
import { STORAGE_KEY } from '../src/StorageKey'
describe('getRefreshToken', () => {
it('returns undefined if tokens are not set', () => {
it('returns undefined if tokens are not set', async () => {
// GIVEN

@@ -12,3 +12,3 @@ // localStorage is empty

// I call getRefreshToken
const result = getRefreshToken()
const result = await getRefreshToken()

@@ -20,3 +20,3 @@ // THEN

it('returns the access token is it is set', () => {
it('returns the access token is it is set', async () => {
// GIVEN

@@ -29,3 +29,3 @@ // Both tokens are stored in localstorage

// I call getRefreshToken
const result = getRefreshToken()
const result = await getRefreshToken()

@@ -32,0 +32,0 @@ // THEN

@@ -1,6 +0,6 @@

import { STORAGE_KEY } from '../src/StorageKey';
import { isLoggedIn } from '../index';
import { STORAGE_KEY } from '../src/StorageKey'
import { isLoggedIn } from '../index'
describe('isLoggedIn', () => {
it('returns false if tokens are not set', () => {
it('returns false if tokens are not set', async () => {
// GIVEN

@@ -12,3 +12,3 @@ // localStorage is empty

// I call isLoggedIn
const result = isLoggedIn()
const result = await isLoggedIn()

@@ -20,3 +20,3 @@ // THEN

it('returns true if refresh token is set', () => {
it('returns true if refresh token is set', async () => {
// GIVEN

@@ -29,3 +29,3 @@ // Both tokens are stored in localstorage

// I call isLoggedIn
const result = isLoggedIn()
const result = await isLoggedIn()

@@ -32,0 +32,0 @@ // THEN

@@ -1,3 +0,3 @@

import { setAccessToken } from '../index';
import { STORAGE_KEY } from '../src/StorageKey';
import { setAccessToken } from '../index'
import { STORAGE_KEY } from '../src/StorageKey'

@@ -14,5 +14,5 @@ describe('setAccessToken', () => {

// I expect an error to have been thrown
expect(() => {
setAccessToken('accesstoken')
}).toThrow('Unable to update access token since there are not tokens currently stored')
expect(async () => {
await setAccessToken('accesstoken')
}).rejects.toThrow('Unable to update access token since there are not tokens currently stored')
})

@@ -29,8 +29,8 @@

// I expect an error to be thrown
expect(() => {
setAccessToken('accesstoken')
}).toThrow('Failed to parse auth tokens: totallynotjson')
expect(async () => {
await setAccessToken('accesstoken')
}).rejects.toThrow('Failed to parse auth tokens: totallynotjson')
})
it('stores the tokens in localstorage', () => {
it('stores the tokens in localstorage', async () => {
// GIVEN

@@ -43,3 +43,3 @@ // localStorage is empty

// I call setAccessToken
setAccessToken('newaccesstoken')
await setAccessToken('newaccesstoken')

@@ -49,4 +49,7 @@ // THEN

const storedTokens = localStorage.getItem(STORAGE_KEY) as string
expect(JSON.parse(storedTokens)).toEqual({ accessToken: 'newaccesstoken', refreshToken: 'refreshtoken' })
expect(JSON.parse(storedTokens)).toEqual({
accessToken: 'newaccesstoken',
refreshToken: 'refreshtoken',
})
})
})

@@ -1,6 +0,6 @@

import { setAuthTokens } from '../index';
import { STORAGE_KEY } from '../src/StorageKey';
import { setAuthTokens } from '../index'
import { STORAGE_KEY } from '../src/StorageKey'
describe('setAuthTokens', () => {
it('stores the tokens in localstorage', () => {
it('stores the tokens in localstorage', async () => {
// GIVEN

@@ -13,3 +13,3 @@ // localStorage is empty

const tokens = { accessToken: 'accesstoken', refreshToken: 'refreshtoken' }
setAuthTokens(tokens)
await setAuthTokens(tokens)

@@ -16,0 +16,0 @@ // THEN

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc