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

Google OAuth生产环境正常,本地开发报origin_mismatch错误求助

Google OAuth 2.0 开发环境 origin_mismatch 问题排查

错误信息

Access blocked: Authorization Error

testemailaddress@gmail.com

You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy.

If you're the app developer, register the JavaScript origin in the Google Cloud Console.
Error 400: origin_mismatch

环境配置

  • 前端:localhost:3000(React)
  • 后端:localhost:8000(Express + Node.js)

Google云控制台配置

已配置以下内容:

  • 授权JavaScript来源:
    • http://localhost:3000
    • https://mywebsite.com(生产环境)
  • 授权重定向URI:
    • http://localhost:8000/api/callback(开发环境)
    • https://mywebsite.com/api/callback(生产环境)

相关代码

后端OAuth路由(auth.js,Express.js)

const express = require("express");
const router = express.Router();
const oauth2Client = require("../config/googleConfig");
const SCOPES = [
    'https://www.googleapis.com/auth/userinfo.profile',
    'https://www.googleapis.com/auth/userinfo.email'
];

// Redirect to Google's OAuth 2.0 server to initiate authentication
router.get('/google', (req, res) => {
    console.log(`/google called`);
    const authUrl = oauth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: SCOPES,
        redirect_uri: 'http://localhost:8000/api/callback' // Explicitly set redirect URI for development
    });
    res.redirect(authUrl);
});

// Handle the OAuth 2.0 server response
router.get('/callback', async (req, res) => {
    console.log(`/callback req.query: `, req.query);
    const { code } = req.query;
    try {
        const { tokens } = await oauth2Client.getToken(code);
        oauth2Client.setCredentials(tokens);
        req.session.tokens = tokens;
        res.redirect('http://localhost:3000'); // Redirect back to frontend after successful login
    } catch (error) {
        console.error('Error during OAuth callback:', error.response ? error.response.data : error);
        res.status(500).send('Authentication failed');
    }
});

module.exports = router;

CORS配置(server.js,Express中间件)

// process.env.CLIENT_URL === http://localhost:3000

app.use(cors({ 
  origin: `${process.env.CLIENT_URL}`,
  credentials: true
}));

Session配置(Express express-session)

app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    store: MongoStore.create({ mongoUrl: process.env.DATABASE }),
    cookie: {
        maxAge: 2 * 60 * 60 * 1000, // 2 hours
        httpOnly: true,
        secure: false, // Set to false in development
        sameSite: 'Lax' // Ensures cookies are accessible across localhost:3000 and localhost:8000
    }
}));

前端React API调用函数

export const googleSignIn = async (token) => { // not the JWT token, the google token
  try {
      const response = await fetch(`${API}/google-login`, {
          method: 'POST',
          headers: {
              Accept: 'application/json',
              'Content-Type': 'application/json',
          },
          credentials: 'include', // Ensure session cookie is included
          body: JSON.stringify({ idToken: token }),
      });
      return await response.json();
  } catch (err) {
      return { error: 'Google sign-in failed. Please try again.' };
  }
};

已尝试的解决措施

  • 反复校验授权来源与重定向URI,确认控制台配置正确
  • 显式设置generateAuthUrl中的重定向URI,与控制台配置一致
  • 调整权限范围为仅用户信息权限,避免冲突
  • 清除localhost浏览器缓存和Cookie,用无痕模式测试
  • 通过浏览器开发者工具确认/api/google路由生成的authUrl与控制台重定向URI一致

观察到的行为

  • 生产环境(https://mywebsite.com)运行正常,用户可正常登录
  • 开发环境中Google OAuth流程最后一步弹出「origin_mismatch」错误

问题核心分析

你的代码逻辑存在流程冲突:后端采用的是授权码流程(跳转Google登录页,回调到后端),但前端却写了前端直接获取ID Token传给后端的逻辑。两种流程的origin校验规则不同:

  • 授权码流程:Google校验的是后端重定向URI的合法性
  • 前端SDK流程:Google校验的是前端页面的origin(localhost:3000)
    这种混用导致开发环境下origin校验不通过。

解决建议

方案1:统一使用后端跳转式OAuth流程

  1. 移除前端googleSignIn相关逻辑,改为让用户直接点击跳转链接到后端的/api/google路由(比如按钮的href设为http://localhost:8000/api/google)
  2. 确保Google云控制台的授权重定向URI与后端generateAuthUrl中的redirect_uri完全一致(当前配置已满足)
  3. 无需在前端引入Google JS SDK,所有OAuth流程由后端处理

方案2:统一使用前端SDK式OAuth流程

  1. 后端移除/google和/callback路由,新增接口接收前端传来的ID Token并验证(用Google官方库校验token合法性)
  2. 确保Google云控制台的授权JavaScript来源包含http://localhost:3000(当前配置已满足)
  3. 前端使用Google JS SDK初始化时,确保client ID正确;若使用redirect_uri需同步配置到控制台
  4. 这种方式无需后端session跳转,直接通过ID Token完成用户认证

额外排查点

  • 确认Google云控制台的项目选择正确,不要误操作到其他项目
  • 检查googleConfig.js中的client ID和client secret是否对应开发环境,避免混用生产环境密钥
  • 确认前端运行协议:控制台配置的是http://localhost:3000,如果前端开启了https,需改为https://localhost:3000并更新控制台配置
  • 清除Google账户的应用授权记录:移除测试应用的授权后重新测试

内容的提问来源于stack exchange,提问作者rom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:01:08