【问题标题】:Trying to redirect client to Google OAuth, getting 405 error尝试将客户端重定向到 Google OAuth,收到 405 错误
【发布时间】:2026-01-01 11:35:02
【问题描述】:

我正在尝试创建一个连接到 Google Calendar API 的 Web 服务。在尝试授权我的应用程序时,我生成了一个具有必要范围的 url。问题是当我尝试将客户端重定向到生成的 url 时,我收到 405 错误并显示以下消息:

对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:8080” 使用权。响应的 HTTP 状态代码为 405。

我大部分时间都在遵循本指南:https://developers.google.com/identity/protocols/OAuth2WebServer 使用 node.js 客户端库。

据我了解,Google 似乎没有将他们的服务器配置为接受跨源请求,我不明白的是,如果我无法从我的服务器发送请求,我应该如何将我的用户重定向到他们的授权页面域。

以下是相关代码:

export function authorize(req, res, callback): any {
  let auth = new googleAuth();
  let oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
  if (// Check if we have previously stored a token.) {
    oauth2Client.credentials = //get token;
    callback(oauth2Client);
  } else {
    //redirect to google authentication page
    let authUrl = oauth2Client.generateAuthUrl({
      access_type: 'offline',
      state: '/',
      scope: SCOPES
    });
    res.redirect(authUrl);
  }
}

【问题讨论】:

  • A 405 表示“方法不允许”,因此在这种情况下,服务器根本不允许对您尝试访问的authUrl URL 的 OPTIONS 请求。我认为这可能与服务器是否接受跨域请求完全无关——但您可以通过使用 curl 或 postman 或其他工具向该authUrl URL 发送 OPTIONS 请求来确认,然后查看您的内容回来。我打赌你会得到 405。
  • 无论如何,只要该服务器向 OPTIONS 请求提供 405,您就无法从前端 JavaScript 代码成功访问其响应。您需要改为从后端代码发出请求。对于基于 OAuth 的服务,情况似乎总是如此——您将无法使用 XHR 或 Fetch API 从它们那里获取您的前端 JavaScript 代码可以访问的响应。
  • @sideshowbarker OPTIONS 请求是来自浏览器的预检请求,而不是我有意做的事情。你是对的,我在使用邮递员时遇到了同样的问题,但是 405 到 OPTIONS 请求仍然是一个问题,因为我正在发出 CORS 请求,所以我必须导航,对吧?如果我确实请求服务器端,用户如何进行身份验证?例如,如果来自 google 示例的链接要求您登录并授予对示例范围的访问权限。我仍然需要用户登录/授予我的应用访问权限。
  • 抱歉格式乱码,这是链接:accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly& access_type=offline& include_granted_scopes=true& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Foauth2.example.com%2Fcallback& response_type=code& client_id= client_id
  • 是的,对不起,我知道 OPTIONS 请求是来自浏览器的预检。我的观点是,这正是问题所在,因为浏览器永远不会在该 OPTIONS 请求中包含任何凭据,并且在发出请求时不会进行任何类型的身份验证。因此,要让它使用 XHR 或 Fetch 处理来自前端 JavaScript 代码的请求,服务器必须不需要身份验证/凭据。但确实如此。

标签: node.js oauth-2.0 cors google-oauth http-status-code-405


【解决方案1】:

原来当 AJAX 收到 300 状态码时,浏览器会自动代表客户端向返回的位置发送另一个 GET 请求。即使我已经解决了我的 CORS 问题,我也必须自己手动加载 html 页面,因为请求是代表客户端发出的。我真正想要的是浏览器向 auth uri 发出请求。

所以我对这个问题的解决方案是在前端检测重定向并让浏览器发出一个全新的 GET 请求。似乎仍然可以解决,所以如果其他人有更好的解决方案,我想听听。

【讨论】:

    【解决方案2】:

    如果有人使用 React 或类似的 SPA 框架来解决与 OAuth 2 相关的问题,请阅读以下内容:

    不要在服务器端重定向。不要这样做(node.js/express 作为后端示例):

    router.get('/go', errorHandler(async (req, res, next) => {
        res.redirect(authenticationUrl);
    })
    );
    

    这样做:

    router.get('/go', errorHandler(async (req, res, next) => {
        res.json({
            redirectUrl: 'https://google.com'
        })
    })
    );
    

    然后在您的前端客户端上,获取响应并进行重定向。示例:

    getUrl = async () => {
        try {
            const res = await API.get(`/go`);
            window.location = res.data.redirectUrl;
        } catch (err) {
            console.log(err);
        }
    }
    

    在 React 中工作。已检查!

    【讨论】:

      【解决方案3】:

      根据流程,它显示为浏览器(APP)-> API(服务器)-> Google auth(重定向),这是 AWS、Google Auth 等身份提供商服务器的常见路径。他们从不发送额外的 ALLOW ORIGIN 标头,这就是浏览器在重定向点拒绝请求的原因

      现在是锻炼解决方案。

      1. 应将App域(http://localhost:3000)添加为IDP服务器的可信域

      2. 向 API 服务器请求 Auth 启动应该是

        window.location.href = 'http://localhost:5000/api/v1/auth/login-google';

      【讨论】: