Я работаю над аутентификацией пользователей для веб-сайта, созданного с использованием стека MERN, и я решил использовать токены JWT, хранящиеся в виде файлов cookie HttpOnly. Файл cookie был отправлен в поле Set-Cookie в заголовке ответа, когда я использовал Postman для выполнения запроса, но не в веб-инспекторе Safari, как показано на изображении ниже. На вкладке «Хранилище» также не найдены файлы cookie.
Я упростил свою форму входа в React до кнопки, которая отправляет имя пользователя и пароль пользователя для отладки.
import React from "react";
const sendRequest = async (event) => {
event.preventDefault();
let response;
try {
response = await fetch("http://localhost:5000/api/user/login", {
method: "POST",
body: { username: "Joshua", password: "qwerty" },
mode: "cors",
// include cookies/ authorization headers
credentials: "include",
});
} catch (err) {
console.log(err);
}
if (response) {
const responseData = await response.json();
console.log(responseData);
}
};
const test = () => {
return (
<div>
<input type="button" onClick={sendRequest} value="send" />
</div>
);
};
export default test;
Я использую экспресс на бэкэнде, и это мой index.js, где сначала принимаются все входящие запросы.
const app = express();
app.use(bodyParser.json());
app.use("/images", express.static("images"));
app.use((req, res, next) => {
res.set({
"Access-Control-Allow-Origin": req.headers.origin,
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "Content-Type, *",
"Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE",
});
next();
});
app.use(cookieParser());
// api requests for user info/ login/signup
app.use("/api/user", userRoutes);
Это промежуточное программное обеспечение, на которое в конечном итоге направляется запрос на вход.
const login = async (req, res, next) => {
const { username, password } = req.body;
let existingUser;
let validCredentials;
let userID;
let accessToken;
try {
existingUser = await User.findOne({ username });
} catch (err) {
return next(new DatabaseError(err.message));
}
// if user cannot be found -> username is wrong
if (!existingUser) {
validCredentials = false;
} else {
let isValidPassword = false;
try {
isValidPassword = await bcrypt.compare(password, existingUser.password);
} catch (err) {
return next(new DatabaseError(err.message));
}
// if password is wrong
if (!isValidPassword) {
validCredentials = false;
} else {
try {
await existingUser.save();
} catch (err) {
return next(new DatabaseError(err.message));
}
userID = existingUser.id;
validCredentials = true;
accessToken = jwt.sign({ userID }, SECRET_JWT_HASH);
res.cookie("access_token", accessToken, {
maxAge: 3600,
httpOnly: true,
});
}
}
res.json({ validCredentials });
};
Дополнительная информация
В промежуточном программном обеспечении для входа в систему устанавливается логическое значение validCredentials, которое возвращается клиенту. Мне удалось получить это значение во внешнем интерфейсе, поэтому я не думаю, что это ошибка CORS. Кроме того, никаких ошибок не возникало, и все другие запросы API на моей веб-странице, которые не используют файлы cookie, также работают нормально.
Еще одна интересная вещь заключается в том, что, несмотря на использование одних и тех же данных (объект JS, содержащий {username:Joshua, password:qwerty}) как для Postman, так и для кода React, validCredentials оценивается как true в Postman и как false в веб-инспекторе. Это существующий документ в моей базе данных, и я ожидаю, что возвращаемое значение будет истинным, как это было до того, как я добавил файлы cookie.
Могу ли я узнать, что я сделал неправильно, или у вас есть какие-либо предложения о том, как я могу решить эту проблему? Я новичок в веб-разработке
ИЗМЕНИТЬ
С ответом Дейва я могу получить заголовок Set-Cookie во внешнем интерфейсе. Однако по какой-то причине он не отображается на вкладке «Хранилище» в веб-инспекторе.
Это заголовок ответа
Это вкладка «Хранилище», где обычно появляются файлы cookie с сайта.