Почему не удается записать токен аутентификации в cookie?
У меня имеется клиент такого вида:
//store для компонента формы логина const login = ref(''); const password = ref(''); const isAuthenticated = ref(false); const respAuthMessage = ref(null); const updateAuthentication = (token) => { // если токен приходит, то меняю тип на boolean isAuthenticated.value = !!token; } const handleSubmit = async () => { const loginData = { login: login.value, password: password.value } try { const resp = await loginUser(loginData); const token = resp.token; respAuthMessage.value = resp; updateAuthentication(token); if (isAuthenticated.value) { router.push('/'); } } catch (error) { console.error('Error:', error); } } //api.js const getData = async (response) => { const data = await response.json(); return data; } async function fetchData(endpoint, requestData) { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData), }; const response = await fetch(`http://localhost:5000/auth/${endpoint}`, requestOptions); return getData(response) } export async function loginUser(loginData) { return fetchData('Login', loginData); } |
//store для компонента формы логина const login = ref(''); const password = ref(''); const isAuthenticated = ref(false); const respAuthMessage = ref(null); const updateAuthentication = (token) => { // если токен приходит, то меняю тип на boolean isAuthenticated.value = !!token; } const handleSubmit = async () => { const loginData = { login: login.value, password: password.value } try { const resp = await loginUser(loginData); const token = resp.token; respAuthMessage.value = resp; updateAuthentication(token); if (isAuthenticated.value) { router.push('/'); } } catch (error) { console.error('Error:', error); } } //api.js const getData = async (response) => { const data = await response.json(); return data; } async function fetchData(endpoint, requestData) { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData), }; const response = await fetch(`http://localhost:5000/auth/${endpoint}`, requestOptions); return getData(response) } export async function loginUser(loginData) { return fetchData('Login', loginData); }
так же сервер:
//index.js import express from "express"; import mongoose from "mongoose"; import authRouter from "./authRouter.js"; import cors from 'cors'; import cookieParser from 'cookie-parser'; const PORT = process.env.PORT || 5000; const app = express(); app.use(express.json()); app.use(cors()); app.use(cookieParser()); app.use("/auth", authRouter); const DB_URL = ...; const start = async () => { try { await mongoose.connect(DB_URL); app.listen(PORT, () => { console.log(`${PORT}`); }); } catch(e) { console.log(e); } } start(); //authController.js import bcrypt from 'bcryptjs'; import jwt from 'jsonwebtoken'; import { secret } from '../config.js' const generateAccessToken = (id, roles) => { const payload = { id, roles, } return jwt.sign(payload, secret, { expiresIn: "24h" }) } class authController { async login(req, res) { try { const { login, password } = req.body const user = await User.findOne({ login }) if(!user) { return res.status(400).json({ message: `User ${ login } not found` }) } const validPassword = bcrypt.compareSync(password, user.password) if(!validPassword) { return res.status(400).json({ message: `Incorrect password entered` }) } const token = generateAccessToken(user._id, user.roles) res.cookie('token', token, { httpOnly: true, maxAge: 3600000 });// не записывает в cookie return res.json({ token }) } catch(e) { console.log(e) res.status(400).json({message: 'Login error'}) } } } |
//index.js import express from "express"; import mongoose from "mongoose"; import authRouter from "./authRouter.js"; import cors from 'cors'; import cookieParser from 'cookie-parser'; const PORT = process.env.PORT || 5000; const app = express(); app.use(express.json()); app.use(cors()); app.use(cookieParser()); app.use("/auth", authRouter); const DB_URL = ...; const start = async () => { try { await mongoose.connect(DB_URL); app.listen(PORT, () => { console.log(`${PORT}`); }); } catch(e) { console.log(e); } } start(); //authController.js import bcrypt from 'bcryptjs'; import jwt from 'jsonwebtoken'; import { secret } from '../config.js' const generateAccessToken = (id, roles) => { const payload = { id, roles, } return jwt.sign(payload, secret, { expiresIn: "24h" }) } class authController { async login(req, res) { try { const { login, password } = req.body const user = await User.findOne({ login }) if(!user) { return res.status(400).json({ message: `User ${ login } not found` }) } const validPassword = bcrypt.compareSync(password, user.password) if(!validPassword) { return res.status(400).json({ message: `Incorrect password entered` }) } const token = generateAccessToken(user._id, user.roles) res.cookie('token', token, { httpOnly: true, maxAge: 3600000 });// не записывает в cookie return res.json({ token }) } catch(e) { console.log(e) res.status(400).json({message: 'Login error'}) } } }
По факту, всё работает хорошо. После регистрации, при логине, я получаю токен, но чего-то он не записывается в cookie. Даже в заголовке ответов в вкладке network я вижу тот самый токен:
Set-Cookie: token=....
Сайт находится на порту 5173, а сервер на 5000. Для корректной работы я использовал cors.
Дополнительно:
Заголовок "Access-Control-Allow-Credentials" выставили?
Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:5173 Connection: keep-alive Content-Length: 205 Content-Type: application/json; charset=utf-8 Date: Mon, 09 Oct 2023 14:08:52 GMT Etag: W/"cd-WkNxHEyDI1rwZH+foiVDjvojblI" Keep-Alive: timeout=5 Set-Cookie: token=...; Max-Age=3600; Path=/; Expires=Mon, 09 Oct 2023 15:08:52 GMT; HttpOnly Vary: Origin X-Powered-By: Express |
Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:5173 Connection: keep-alive Content-Length: 205 Content-Type: application/json; charset=utf-8 Date: Mon, 09 Oct 2023 14:08:52 GMT Etag: W/"cd-WkNxHEyDI1rwZH+foiVDjvojblI" Keep-Alive: timeout=5 Set-Cookie: token=...; Max-Age=3600; Path=/; Expires=Mon, 09 Oct 2023 15:08:52 GMT; HttpOnly Vary: Origin X-Powered-By: Express
Firefox пишет ошибки в консоль при невозможности записать куки. Попробуйте в нём.
Ответы:
Браузер по умолчанию запрещает Javascript записывать куки для доменов используйте прокси
- HttpOnly куки сетятся на сервере.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Есть несколько возможных причин, по которым у вас может не получаться записать токен аутентификации в cookie. Давайте рассмотрим некоторые из них:
1. Неправильная установка параметров cookie:
Убедитесь, что вы правильно устанавливаете параметры cookie, такие как срок действия, путь и домен. Например, если вы пытаетесь установить cookie сроком на 1 день, но указываете неправильный формат срока действия, то cookie может не устанавливаться.
2. Проблемы с безопасностью:
Браузеры имеют различные политики безопасности, которые могут предотвращать установку некоторых cookie. Например, если ваш сайт не использует HTTPS, то браузеры могут блокировать установку cookie с помеченным атрибутом Secure.
3. Проблемы с SameSite:
Недавно был введен атрибут SameSite для cookie, который помогает защитить пользователей от некоторых видов атак. Убедитесь, что вы правильно устанавливаете этот атрибут в соответствии с вашими требованиями безопасности.
4. Проблемы с путем cookie:
Убедитесь, что вы правильно указываете путь для cookie. Если вы устанавливаете cookie на одной странице, а пытаетесь получить его на другой, то cookie может быть недоступен из-за неправильно указанного пути.
Вот пример кода на PHP, который может помочь вам установить cookie с токеном аутентификации:
Убедитесь, что вы правильно настроили параметры cookie и следуете рекомендациям безопасности. Если проблема сохраняется, проверьте консоль браузера на наличие ошибок и попробуйте провести отладку вашего кода.