Comments (5)
- storing the tokens should be beyond the scope of this library.
ITokenStorage
interface with default implementation using LocalStorage could be provided.
from axios-jwt.
Isn't calling an endpoint a lot more time consuming than parsing a token?
from axios-jwt.
What do you mean? In the current implementation:
- Tokens are stored as object in LS, not primitives. So JSON.parse is called on each API call to retrieve the tokens,
- Token is parsed on each API call (expensive),
- An external dependency is required in order to parse the token (and this dependency breaks on webpack 5).
Assume that the token is valid and make your fetch request. 401 should occur only when the backend says so. Not necessarily when the token is expired (e.g. could be revoked).
from axios-jwt.
Here is a very basic implementation:
// TODO: handle concurrent requests with 401 response
import { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
import { refreshTokens } from './auth';
const ACCESS_KEY_LS_KEY = 'accessToken';
const REFRESH_KEY_LS_KEY = 'refreshToken';
type Token = string;
interface IAuthTokens {
accessToken: Token;
refreshToken: Token;
}
export const setAuthTokens = (tokens: IAuthTokens): void => {
localStorage.setItem(ACCESS_KEY_LS_KEY, tokens.accessToken);
localStorage.setItem(REFRESH_KEY_LS_KEY, tokens.refreshToken);
};
/**
* Clears both tokens
*/
const clearAuthTokens = (): void => {
localStorage.removeItem(ACCESS_KEY_LS_KEY);
localStorage.removeItem(REFRESH_KEY_LS_KEY);
};
/**
* Returns the stored refresh token
* @returns {string} Refresh token
*/
const getRefreshToken = (): Token | undefined => {
const tokens = getAuthTokens();
return tokens ? tokens.refreshToken : undefined;
};
/**
* Returns the stored access token
* @returns {string} Access token
*/
const getAccessToken = (): Token | undefined => {
const tokens = getAuthTokens();
return tokens ? tokens.accessToken : undefined;
};
export const applyAuthTokenInterceptor = (axios: AxiosInstance, config: IAuthTokenInterceptorConfig): void => {
if (!axios.interceptors) throw new Error(`invalid axios instance: ${axios}`);
axios.interceptors.request.use(authTokenInterceptor(config));
axios.interceptors.response.use(undefined, async (e: AxiosError) => {
if (e.response?.status === 401) {
try {
isRefreshing = true;
const tokens = await refreshTokens(getRefreshToken());
setAuthTokens(tokens);
resolveQueue(tokens.accessToken);
return axios.request(e.config);
} catch (error) {
console.error('applyAuthTokenInterceptor:error', error);
declineQueue(error);
clearAuthTokens();
throw error;
} finally {
isRefreshing = false;
}
} else {
return e;
}
});
};
const getAuthTokens = (): IAuthTokens | undefined => {
const accessToken = localStorage.getItem(ACCESS_KEY_LS_KEY);
const refreshToken = localStorage.getItem(REFRESH_KEY_LS_KEY);
return { accessToken, refreshToken };
};
interface IAuthTokenInterceptorConfig {
header?: string;
headerPrefix?: string;
}
const authTokenInterceptor =
({ header = 'Authorization', headerPrefix = 'Bearer' }: IAuthTokenInterceptorConfig) =>
async (requestConfig: AxiosRequestConfig): Promise<AxiosRequestConfig> => {
if (isRefreshing) {
return new Promise((resolve, reject) => {
queue.push({ resolve, reject });
})
.then((token: string) => {
requestConfig.headers[header] = `${headerPrefix}${token}`;
return requestConfig;
})
.catch(Promise.reject);
}
const accessToken = getAccessToken();
requestConfig.headers[header] = `${headerPrefix} ${accessToken}`;
return requestConfig;
};
type RequestsQueue = {
resolve: (value?: unknown) => void;
reject: (reason?: unknown) => void;
}[];
let isRefreshing = false;
let queue: RequestsQueue = [];
const resolveQueue = (token?: Token) => {
queue.forEach((p) => {
p.resolve(token);
});
queue = [];
};
const declineQueue = (error: Error) => {
queue.forEach((p) => {
p.reject(error);
});
queue = [];
};
from axios-jwt.
@magom001 Perhaps you could turn this into a PR?
from axios-jwt.
Related Issues (20)
- [React Native] Not working
- Support rotating refresh tokens
- Retry failed request after RefreshToken HOT 2
- SECURITY: Token should not be stored in the localstorage to limit XSS vulnerability HOT 9
- Breaks on axios > 0.21.4
- Allow a different storage. HOT 9
- Version 2 breaks react 18 support
- localstorage is not defined HOT 2
- Non-typescript usage examples? HOT 4
- 'getStorage' does not exist in type 'IAuthTokenInterceptorConfig' HOT 3
- undefined window and Synchronous isLoggedIn HOT 4
- Uncaught TypeError: (0 , ms_1.default) is not a function HOT 6
- No requests are made if applyAuthTokenInterceptor called HOT 1
- StorageType undefined outside the interceptor? HOT 1
- Feature Request: Allow prepended string for token names
- not setting header HOT 4
- Return interceptor HOT 2
- How to deal with refresh tokens that are expired? HOT 10
- [React Native] Not working HOT 10
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from axios-jwt.