Ошибка при авторизации на JS
Я прописала, что хочу, чтобы каталог был доступен только авторизованному пользователю. Сама авторизация, по идее, отрабатывает, но при попытке попасть на страницу каталога все равно выдает:
{"text":"Пользователь не авторизован!","status":401}
В проекте использую svelte. Функция логина в контроллере:
exports.login = (req, res, next) => {
passport.authenticate('local',
(err, user, info) => {
if (err) return next(err)
if (!user) return res.status(401).json(new ResObj({
text: exceptions.USER_NOT_AUTH,
}))
req.login(user, (err) => {
if (err) return next(err)
return res.send(new ResObj({
text: exceptions.SUCCESS_OPERATION,
}))
})
}
)(req, res, next)
}
скрипт на странице каталога:
<script>
import { onMount } from 'svelte';
import ProductCard from '../../components/product/ProductCard.svelte';
let products = [];
onMount(async () => {
const res = await fetch('http://localhost:3000/product/all', {
credentials: 'include'
});
products = (await res.json()).data;
// console.log(products);
});
</script>
Путь, прописанный на сервере:
server.use('/product', isAuthenticated, productRouter)
Функция на проверку авторизации:
exports.isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
res.send({
text: exceptions.USER_NOT_AUTH,
status: 401
})
};
И сам роутер каталога, если вдруг нужен:
const express = require("express");
const productController = require("../controllers/product.controller")
const productRouter = express.Router();
productRouter.get("/all", productController.getAllProducts);
module.exports = productRouter
Ответы (1 шт):
Скорее всего, проблема связана с сессией или куками при аутентификации. Разберем возможные причины:
- Отсутствие или неправильная передача куков Вы передаете { credentials: 'include' } в fetch, что правильно. Однако браузер будет отправлять куки только в том случае, если:
Сервер правильно их устанавливает (Set-Cookie). На клиенте разрешены сторонние куки (если фронтенд и бэкенд на разных доменах). Запросы идут по одному домену (если localhost, то у вас это работает, но в проде важно). Проверка: В браузере откройте DevTools (F12) → Network → Ваш запрос к /product/all и посмотрите, отправляется ли кука сессии. В DevTools → Application → Cookies проверьте, создается ли кука после логина.
- Проблема с сессиями в express-session Если используете express-session, убедитесь, что сервер правильно сохраняет сессию:
Проверьте, как настроен express-session В server.js или app.js должен быть такой код:
const session = require('express-session');
const passport = require('passport');
app.use(session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: false, // Должно быть `true`, если HTTPS
sameSite: 'lax' // Или 'none', если фронт и бэк на разных доменах
}
}));
app.use(passport.initialize());
app.use(passport.session());
Если secure: true, то сессия работать не будет в localhost, потому что там нет HTTPS.
- Проблема с req.login Вы вызываете req.login(user, (err) => {...}), но не возвращаете саму сессию клиенту. После успешного логина попробуйте добавить:
req.login(user, (err) => {
if (err) return next(err);
res.cookie('connect.sid', req.sessionID, {
httpOnly: true,
secure: false, // Если на HTTPS, поменяйте на true
sameSite: 'lax'
});
return res.send(new ResObj({
text: exceptions.SUCCESS_OPERATION,
}));
});
- Фронтенд и бэкенд на разных доменах Если клиент работает на http://localhost:5173, а сервер на http://localhost:3000, сессии могут не передаваться из-за CORS.
Решение: В server.js добавьте CORS:
const cors = require('cors');
app.use(cors({
origin: 'http://localhost:5173',
credentials: true
}));
- Проблема с isAuthenticated Попробуйте перед req.isAuthenticated() залогировать сессию:
exports.isAuthenticated = (req, res, next) => {
console.log('Session:', req.session);
console.log('User:', req.user);
if (req.isAuthenticated()) {
return next();
}
res.status(401).json({
text: exceptions.USER_NOT_AUTH,
status: 401
});
};
Если req.user === undefined, значит, сессия не сохраняется.