Не получается обновить accessToken
Пишу свой проект, с целью изучения фронтенда (поэтому много говнокода, за советы также буду благодарен)
Пытаюсь получить доступ к всем данным пользователей по запросу api.get('/users')
const getUsers = (req, res, next) => {
const db = low(adapter)
const result = authMiddleware(req, res) // Я пробовал запихнуть его как middleware, но почему-то происходит бесконечная попытка отправить запрос, посмотрю позже
if (result === 401) { return res.sendStatus(401) }
let DB = db.get('users').value()
res.json(DB)
return
}
// authMiddleware - src/middleware/auth
const jwt = require('jsonwebtoken');
const { access_secret, refresh_secret, tokens } = require('../config/config').config
const { validateAccessToken } = require('../service/token')
const authMiddleware = (req, res) => {
const authHeader = req.headers.authorization
if (!authHeader) { return 401 }
const accessToken = authHeader.split(' ')[1]
if (!accessToken) { return 401 }
const tokenData = validateAccessToken(accessToken) // Возвращает null так как токен сдох, но мы же его обновили?
if (!tokenData) { return 401 }
req.user = tokenData
return req
}
module.exports = { authMiddleware }
Проблема:
При истечении срока жизни accessToken я отправляю запрос на обновление пары токенов. Отслеживаю с помощью кастомного axios'а
// src/http/axios
import axios from 'axios'
const api = axios.create({
withCredentials: true,
})
api.interceptors.request.use((config) => {
config.headers.common['Authorization'] = `Bearer ${localStorage.getItem('token')}`
return config
})
api.interceptors.response.use((config) => {
return config
}, async (error) => {
const originalRequest = error.config
if (error.response.status === 401) {
try {
const response = await api.post('/api/refresh', {withCredentials: true})
localStorage.setItem('token', response.data.accessToken)
return api.request(originalRequest)
} catch (error) {
console.error(error)
}
}
})
export default api
При попытке обновить токен, данный код входит в цикл, так как почему-то токен не обновился и он все еще не рабочий
Посмотрел, что дает api.post, он возвращает сначала несколько раз старый токен, а потом новый, и все повторяется
На стороне сервера:
const refresh = (req, res) => {
const { refreshToken } = req.cookies
const result = refreshThisToken(refreshToken)
if (result === 401) {
res.sendStatus(401)
} else {
res.cookie('refreshToken', result.refreshToken, { httpOnly: true, maxAge: 1000 * 60 * 5 }).json(result).send()
return
}
res.send()
}
На стороне сервиса по обновлению refreshToken'а
const refreshThisToken = (refreshToken) => {
const db = low(adapter)
if (!refreshToken) {
return 401
}
const tokenData = validateRefreshToken(refreshToken)
const getToken = db.get('users').find({ refreshToken: refreshToken }).value()
if (!tokenData || !getToken) {
return 401
}
const user_data = {
userMail: getToken.userMail,
userLogin: getToken.userLogin,
userName: getToken.userData.userName,
contacts: getToken.userData.contacts,
url: getToken.userData.url
}
const tokens = generateTokens(user_data)
saveToken(user_data.userLogin, tokens.refreshToken)
return tokens
}
Здесь должно быть все хорошо, проходит все без 401, это и видно в браузере по запросам, но запрос к get /users возвращает 401, тк validateAccessToken вернул 401
Глаза уже замылились, не вижу, что я упустил
Всем спасибо!
Ответы (1 шт):
Я совершенно смотрел не туда, оказывается в originalRequest параметр headers.Authorization токен не менялся и код входил в цикл) Мне просто нужно было обновить его, думал этим занимается верхний интерцептор, доставая токен из localStorage, но оказалось все иначе!
Правильный код:
// src/http/axios
import axios from 'axios'
const api = axios.create({
withCredentials: true,
})
api.interceptors.request.use((config) => {
config.headers.common['Authorization'] = `Bearer ${localStorage.getItem('token')}`
return config
})
api.interceptors.response.use((config) => {
return config
}, async (error) => {
const originalRequest = error.config
if (error.response.status === 401) {
try {
const response = await api.post('/api/refresh', {withCredentials: true})
originalRequest.headers.Authorization = `Bearer ${response.data.accessToken}` // New!
localStorage.setItem('token', response.data.accessToken)
return api.request(originalRequest)
} catch (error) {
console.error(error)
}
}
})
export default api