Google OAuth 登录后将 JWT 从后端发送到前端时出现问题

问题描述 投票:0回答:1

我正在通过构建一个小项目来学习身份验证和 JWT。但在用户使用 Google OAuth 登录后,我一直试图将 JWT(JSON Web 令牌)发送回前端。问题是,当后端登录后重定向时,它会丢失包含 JWT 的标头。

我使用的是:React 和 Vite 作为前端,Node.js 和 Express.js 作为后端。对于 Google 身份验证,我使用 Passport.js 中名为 Passport-google-oauth20 的策略,并进行了一些调整。

这是我的 Google 身份验证策略和路由的后端代码片段:

// Backend Code Snippet

passport.use(new GoogleStrategy(
    {
        clientID: process.env.GOOGLE_CLIENT_ID,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        callbackURL: process.env.FRONTEND_URL + "/auth/google/callback",
    },
    async (accessToken, refreshToken, profile, cb) => {
        try {
            // Logic to create or find user
            // ...
            return cb(null, user);
        } catch (error) {
            return cb(error);
        }
    }
));

router.get("/google", passport.authenticate("google", { scope: ["profile"] }));

router.get(
    "/google/callback",
    passport.authenticate("google", {
        session: false,
        failureRedirect: process.env.FRONTEND_URL + "/auth/login",
    }),
    authController.google_callback
);

这是我生成 JWT 并在 google_callback 函数中设置标头的方法:

// Google Callback Implementation

exports.google_callback = asyncHandler(async (req, res, next) => {
    let user = req.user;
    !user && res.redirect(frontend_url + "/auth/login");
    const opts = {};
    opts.expiresIn = 3600; // 1 hour
    const token = jwt.sign({ user }, secret, opts);

    res.setHeader("authorization", `Bearer ${token}`);
    res.setHeader("Access-Control-Expose-Headers", "authorization");
    // res.redirect(frontend_url + "/");
    res.status(200).json({
        status: "success",
        token: token,
    });
});

尽管我付出了努力,但我还没有找到一种方法可以将 JWT 发送回前端而不丢失它。我能够访问 Google 身份验证的唯一方法是从前端重定向,如下所示:

// Frontend Code Snippet

<a href={import.meta.env.VITE_BACKEND_URL + "/auth/google"}>
    Continue with Google
</a>

并且使用 Axios 进行 GET 请求会导致 CORS 问题:

Access to XMLHttpRequest at 'backend_url/auth/google' from origin 'frontend' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. 

如果有人有将 Google OAuth 与 JWT 身份验证集成的经验,我真的很感激一些指导。预先感谢您的帮助。

我预计将 JWT 与重定向一起发送到响应的标头中,然后打算将其存储在我前端的本地存储中。但是,当我使用 res.redirect 时,令牌丢失了。另外,当使用 res.json 时,我面临着无法在前端重定向和存储令牌的困境。

node.js authentication oauth-2.0 jwt passport.js
1个回答
0
投票

要解决 Google OAuth 登录后将 JWT 发送回前端的问题,您需要稍微修改一下方法,以确保 JWT 正确包含在响应中。

  1. 修改后端代码:

在您的 google_callback 函数中,您当前正在响应标头中设置 JWT,并尝试发送 JSON 响应。但是,您无法在单个响应中同时重定向和发送标头。相反,您应该发送带有令牌的 JSON 响应,或者使用包含令牌的查询参数进行重定向。

以下是修改后端代码以在 JSON 响应中发送令牌的方法:

exports.google_callback = asyncHandler(async (req, res, next) => {
let user = req.user;
if (!user) {
    return res.status(401).json({ error: "User not found" });
}

const opts = {};
opts.expiresIn = 3600; // 1 hour
const token = jwt.sign({ user }, secret, opts);

// Send the token in the response body
return res.status(200).json({
    status: "success",
    token: token,
});

});

  1. 前端代码:

修改后端以在响应正文中发送令牌后,您可以在前端代码中处理它。您可以使用 JavaScript 从响应中提取令牌并将其存储在本地存储中以供将来使用。

以下是如何在前端代码中处理令牌的基本示例:

fetch(`${import.meta.env.VITE_BACKEND_URL}/auth/google/callback`, {
    method: "GET",
    credentials: "include",
})
    .then((response) => response.json())
    .then((data) => {
        const token = data.token;
        localStorage.setItem("token", token);
    })
    .catch((error) => {
        console.error("Error:", error);
    });

  1. 其他注意事项:

确保您的前端代码安全地处理 JWT,例如在后续请求中验证它并防止 XSS 攻击。 考虑使用 HTTPS 进行后端到前端的通信,以确保令牌传输的安全性。

© www.soinside.com 2019 - 2024. All rights reserved.