Приветствую, дорогой читатель! Хочу поделиться решением наболевшей проблемы — автоматическим обновлением access-токена при истечении его срока действия.
Эталонный сценарий
-
Пользователь успешно авторизуется, после чего access- и refresh-токены сохраняются в куки.
-
Время жизни access token заканчивается, нужно запросить новый с использованием refresh.
-
Перед отправкой запроса, требующего 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.
-
Создать флаг, который будет указывать, запрашивается ли сейчас новый access-токен.
-
Организовать очередь запросов, требующих access-токена. Останавливать их и ждать завершения получения нового токена.
-
После успешного получения токена достать запросы из очереди и продолжить их выполнение.
Как это реализовать?
Воспользуемся библиотекой 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/
Добавить комментарий