You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js后端通过React API设置Cookie失败,疑client.verifyIdToken问题求助

问题:React调用Node.js后端API无法设置Cookie,无响应无报错

我尝试通过React调用Node.js后端API在浏览器中设置Cookie,但无法成功设置,既没有返回响应也没有报错。请问是否是client.verifyIdToken函数导致了该问题?

Node.js后端代码

export const googleAuth = async (req, res) => {
    const {tokenId} = req.body
    client.verifyIdToken({idToken: tokenId, audience: process.env.GOOGLE_CLIENT_ID}).then((response) => {
        const {email_verified, name, email} = response.payload
        console.log(response.payload)
        if (email_verified) {
            Users.findOne({where: {email: email}}).then(user => {
                if (user) {
                    try {
                        const userId = user.id
                        console.log('user id', userId)
                        const refreshToken = jwt.sign({userId}, process.env.REFRESH_TOKEN_SECRET, {expiresIn: '1d'})
                        Users.update({refreshToken: refreshToken}, {where: {id: userId}})
                        res.cookie('refreshToken', refreshToken, {
                            httpOnly: false,
                            maxAge: 24 * 60 * 60 * 1000,
                        });

                    } catch (err) {
                        console.log(err)
                    }

                } else {
                    try {
                        const salt = bcrypt.genSaltSync(2);
                        const hashPassword = bcrypt.hashSync(email + process.env.ACCESS_TOKEN_SECRET, salt);
                        const refreshToken = jwt.sign({email}, process.env.REFRESH_TOKEN_SECRET, {expiresIn: '1d'})
                        console.log('refresh token', refreshToken)
                        Users.create({
                            name: name,
                            email: email,
                            password: hashPassword,
                            refresh_token: refreshToken,
                            verified: true
                        })
                        res.cookie('refreshToken', refreshToken, {
                            httpOnly: true,
                            maxAge: 24 * 60 * 60 * 1000,
                        });

                    } catch (err) {
                        console.log(err)
                    }


                }
            })
        }
    })

}

React前端代码

const responseSuccessGoogle = async (response) => {
        try {
            console.log(response)
            let result = await axios.post('http://localhost:5000/google-login', {tokenId: response.tokenId},{withCredentials:true})
            setAuth(result.data != null)
            navigate('/profile')
            console.log(result.data)
        } catch (error) {
            console.log(error)
        }

    }

问题分析与修复方案

1. 核心问题:无响应返回

你的代码存在一个致命问题:所有分支都没有向客户端发送响应(比如res.json()/res.send())。哪怕client.verifyIdToken验证成功、Cookie设置完成,客户端请求会一直处于挂起状态,自然看不到响应也不会触发报错。

另外,client.verifyIdToken如果验证失败(比如token无效、audience不匹配),当前代码没有错误处理分支,会直接静默失败,同样不会给客户端返回任何信息。

2. 数据库异步操作未等待

Users.update和Users.create都是异步操作,你没有用await等待它们完成就设置Cookie,可能导致数据库操作还没结束,请求就已经(没)响应了。

3. 跨域配置缺失

前端localhost:3000和后端localhost:5000属于跨域场景,需要在Node.js后端配置CORS允许携带凭据:

const cors = require('cors');
app.use(cors({
  origin: 'http://localhost:3000',
  credentials: true
}));

修复后的Node.js代码

export const googleAuth = async (req, res) => {
  try {
    const { tokenId } = req.body;
    // 处理verifyIdToken的异步和错误
    const response = await client.verifyIdToken({
      idToken: tokenId,
      audience: process.env.GOOGLE_CLIENT_ID
    });
    const { email_verified, name, email } = response.payload;
    console.log(response.payload);

    if (!email_verified) {
      return res.status(400).json({ message: "邮箱未验证" });
    }

    const user = await Users.findOne({ where: { email: email } });
    if (user) {
      const userId = user.id;
      console.log('user id', userId);
      const refreshToken = jwt.sign({ userId }, process.env.REFRESH_TOKEN_SECRET, { expiresIn: '1d' });
      // 等待数据库更新完成
      await Users.update({ refreshToken: refreshToken }, { where: { id: userId } });
      res.cookie('refreshToken', refreshToken, {
        httpOnly: true, // 统一设为true更安全
        maxAge: 24 * 60 * 60 * 1000,
        sameSite: 'lax', // 跨域场景建议设置
      });
      // 返回响应
      return res.json({ success: true, message: "登录成功" });
    } else {
      const salt = bcrypt.genSaltSync(2);
      const hashPassword = bcrypt.hashSync(email + process.env.ACCESS_TOKEN_SECRET, salt);
      const refreshToken = jwt.sign({ email }, process.env.REFRESH_TOKEN_SECRET, { expiresIn: '1d' });
      console.log('refresh token', refreshToken);
      // 等待数据库创建完成
      await Users.create({
        name: name,
        email: email,
        password: hashPassword,
        refresh_token: refreshToken,
        verified: true
      });
      res.cookie('refreshToken', refreshToken, {
        httpOnly: true,
        maxAge: 24 * 60 * 60 * 1000,
        sameSite: 'lax',
      });
      // 返回响应
      return res.json({ success: true, message: "注册并登录成功" });
    }
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "服务器内部错误" });
  }
};

关键修复点

  • 用async/await替代嵌套.then(),统一捕获所有异步错误
  • 给所有分支添加响应返回,确保客户端能收到结果
  • 等待数据库异步操作完成,避免数据不一致
  • 统一Cookie配置,添加sameSite适配跨域场景
  • 后端配置CORS允许跨域携带凭据

内容的提问来源于stack exchange,提问作者Josip Marić

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 04:15:41