当我尝试在请求中创建产品时,我的应用程序没有发送刷新令牌 cookie。
首先,当我登录时,我的refreshToken被设置为cookie,我可以在开发者工具的应用程序部分看到它。
export const login = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email: email });
console.log(user);
if (!user) return res.status(400).json({ msg: "User does not exist. " });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ msg: "Invalid credentials. " });
let accessToken, refreshToken;
try {
accessToken = jwt.sign(
{ userId: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: "2m" }
);
refreshToken = jwt.sign(
{ userId: user._id },
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: "7d" }
);
const SetCookie = res.cookie("refreshToken", refreshToken, {
httpOnly: true,
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
})
console.log(SetCookie)
} catch (err) {
console.error(err);
res
.status(500)
.json({ message: "Signing up failed, please try again later." });
}
res.status(200).json({ message: "logged in!", user, accessToken, refreshToken });
} catch (err) {
console.error(err);
res.status(500).json({ error: err.message });
}
}
然后,我等待 jwt 令牌过期,以测试我的刷新令牌在创建产品时是否有效。 这是设置配置的 asyncThunk,withCredentials:true 允许 axios 向我的服务器发送 cookie。
export const addProduct = createAsyncThunk(
'product/addProduct',
async (productData, { rejectWithValue }) => {
try {
const { user, token, formData } = productData;
const url = `http://localhost:3005/product/${user._id}/add-product`;
const config = {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data',
},
withCredentials: true,
};
const response = await axios.post(url, formData, config,);
console.log(response);
const newProduct = response.data.product;
return newProduct;
} catch (error) {
console.error(error);
console.error(error?.response?.data ?? error.message);
return rejectWithValue(error.response.data);
}
}
);
但是发生错误并表示身份验证失败,因为 jwt 令牌已过期。此错误来自处理受保护路由的身份验证的 checkAuth 函数。问题是,当我尝试在 if 语句之外进行控制台记录时, req.cookies.refreshToken 未定义。这意味着 cookie 不会发送到后端。 这是检查验证码:
export const checkAuth = async (req, res, next) => {
try {
const authHeader = req.headers.authorization;
if (!authHeader) {
throw new Error("Authentication failed!");
}
const token = authHeader.split(" ")[1]; // Authorization: Bearer <token>
const decodedToken = jwt.verify(token, process.env.JWT_SECRET);
req.userData = { userId: decodedToken.userId };
console.log(`DecodedToken Time : ${decodedToken.exp}`)
console.log(`Start, ${token}, end`)
const currentTime = Date.now() / 1000; // convert to seconds
// const currentTime = Math.floor(Date.now() / 1000); // convert to seconds
if (decodedToken.exp - currentTime < 60) {
const rToke = req.headers.cookie
const refreshToken = rToke.split('=')[1];
console.log(`refreshToken:${refreshToken}`)
// Access token has expired, try to refresh using refresh token
// console.log(refreshToken)
if (!refreshToken) {
throw new Error("Refresh token not found!");
}
try {
const decodedRefreshToken = jwt.verify(
refreshToken,
process.env.REFRESH_TOKEN_SECRET
);
console.log(decodedRefreshToken, 'refresh token was verified!')
} catch (error) {
console.error(error)
}
// Validate the user from the decodedRefreshToken if necessary
// Generate a new access token and refresh token
const newAccessToken = jwt.sign(
{ userId: decodedToken.userId },
process.env.JWT_SECRET,
{ expiresIn: "3m" }
);
const newRefreshToken = jwt.sign(
{ userId: decodedToken.userId },
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: "7d" }
);
res.cookie("refreshToken", newRefreshToken, { httpOnly: true });
// Send the new access token in the response headers
console.log(newAccessToken)
res.set("Authorization", `Bearer ${newAccessToken}`);
// res.json({newAccessToken})
} else {
const decodedToken = jwt.verify(token, process.env.JWT_SECRET);
}
next();
} catch (err) {
const error = new HttpError('Authentication failed', 401);
return next(error);
}
};
更令人困惑的是,我已将服务器配置为接受 cookie 以及跨源请求。 这是来自服务器的 index.js 的代码:
app.use(cors({
origin: 'http://localhost:3000',
credentials: true,
cookie: {
domain: 'localhost',
},
}));
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS, DELETE');
next();
});
app.use(cookieParser());
那么为什么刷新令牌不作为 cookie 发送到我的后端呢? cookie 的路径设置为“/”,域设置为“localhost”。任何帮助将非常感激。谢谢。
据我所知,刷新令牌仅适用于 https cookie。 尝试将其更改为https协议。它确实有效。