Работа с JWT-токенами в браузере без боли и страданий

от автора

Приветствую, дорогой читатель! Хочу поделиться решением наболевшей проблемы — автоматическим обновлением access-токена при истечении его срока действия.

Эталонный сценарий

  1. Пользователь успешно авторизуется, после чего access- и refresh-токены сохраняются в куки.

  2. Время жизни access token заканчивается, нужно запросить новый с использованием refresh.

  3. Перед отправкой запроса, требующего acess-токен, проверяем его наличие. Если его нет, отправляем запрос на получение нового.

Пример такой реализации:

api.interceptors.request.use(   async (config: AxiosRequestConfig) => {     let accessToken = getCookie('accessToken');          if (!accessToken) {       accessToken = await refreshAccessToken();     }          if (accessToken && config.headers) {       config.headers.Authorization = `Bearer ${accessToken}`;     }          return config;   },   (error: AxiosError) => {     return Promise.reject(error);   } );  const fetchUser = async () => {   const response = await api.get('/user');   return response.data; }

На первый взгляд всё верно, и такой код действительно работает. Но представьте ситуацию: access-токен устарел, и пользователь переходит на новую страницу, где отправляется несколько запросов, требующих токена. Поскольку токен отсутствует, каждый запрос попытается обновить его, не зная, что другой запрос уже это делает.

Правильный сценарий

Вернёмся к моменту, когда мы проверяем наличие токена:

if (!accessToken) {     accessToken = await refreshAccessToken(); }

Воспользуемся библиотекой axios-jwt-refresh-token.

  1. Создать флаг, который будет указывать, запрашивается ли сейчас новый access-токен.

  2. Организовать очередь запросов, требующих access-токена. Останавливать их и ждать завершения получения нового токена.

  3. После успешного получения токена достать запросы из очереди и продолжить их выполнение.

Как это реализовать?

Воспользуемся библиотекой axios-jwt-refresh-token. Установим необходимые пакеты:

npm install axios-jwt-refresh-token axios js-cookie

Настроим обработчик для Axios:

import axios from 'axios'; import { createTokenRefreshMiddleware } from 'axios-jwt-refresh-token';  // 1. Создаём экземпляр Axios const axiosInstance = axios.create();  // 2. Функция для обновления токенов const requestNewTokens = async () => {   const response = await axios.post('/auth/refresh');   // Важно вернуть объект в таком формате   return {     accessToken: response.data.access_token,     // Если refresh-токен не нужен, просто удалите эту строку     refreshToken: response.data.refresh_token    }; };  // 3. Создаём middleware для обработки токенов const requestAccessMiddleware = createTokenRefreshMiddleware({   requestTokens: requestNewTokens,   onRefreshAndAccessExpire: () => {     // Обработка истёкшей сессии     window.location.href = '/login';   },   accessTokenKey: 'accessToken',   refreshTokenKey: 'refreshToken',   cookiesOptions: { secure: true, sameSite: 'strict' } });  // 4. Подключаем middleware к Axios axiosInstance.interceptors.request.use(requestAccessMiddleware);

Теперь при использовании этого экземпляра Axios вам не нужно вручную передавать access-токен — всё будет работать автоматически.


ссылка на оригинал статьи https://habr.com/ru/articles/931190/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *