GithubHelp home page GithubHelp logo

Breaks on webpack 5 about axios-jwt HOT 5 OPEN

jetbridge avatar jetbridge commented on September 21, 2024
Breaks on webpack 5

from axios-jwt.

Comments (5)

magom001 avatar magom001 commented on September 21, 2024 1
  • storing the tokens should be beyond the scope of this library. ITokenStorage interface with default implementation using LocalStorage could be provided.

from axios-jwt.

mvanroon avatar mvanroon commented on September 21, 2024

Isn't calling an endpoint a lot more time consuming than parsing a token?

from axios-jwt.

magom001 avatar magom001 commented on September 21, 2024

What do you mean? In the current implementation:

  1. Tokens are stored as object in LS, not primitives. So JSON.parse is called on each API call to retrieve the tokens,
  2. Token is parsed on each API call (expensive),
  3. 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.

magom001 avatar magom001 commented on September 21, 2024

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.

mvanroon avatar mvanroon commented on September 21, 2024

@magom001 Perhaps you could turn this into a PR?

from axios-jwt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.