用于服务器端 Web 应用的 Google Oauth2 的 CORS 问题

Posted

技术标签:

【中文标题】用于服务器端 Web 应用的 Google Oauth2 的 CORS 问题【英文标题】:CORS issue with Google Oauth2 for server side webapps 【发布时间】:2018-08-02 04:05:49 【问题描述】:

我在 SO 上提到了这个问题:Google oauth 400 response: No 'Access-Control-Allow-Origin' header is present on the requested resource 但建议的解决方案是针对 Javascript web 应用程序 使用 implicit grant flow

我的设置是这样的,我的前端是基于 angular 4 构建的,但我将它打包并将其与 rest api 一起部署在同一台服务器上。 Si 我正在关注服务器端 Web 应用程序流程:https://developers.google.com/identity/protocols/OAuth2WebServer (下例中服务器端口为 8300)

我已授权 http://localhost:8300 作为 javascript 来源,并从 Angular 应用程序向位于 http://localhost:8300/auth/oauth/test 的 rest api 发出请求 但我仍然收到 CORS 错误:

加载失败 https://accounts.google.com/o/oauth2/v2/auth?client_id=568176070083-1lc20949a0q58l0rhmq93n95kvu8s5o6.apps.googleusercontent.com&redirect_uri=http://localhost:8300/auth/myauth/oauth/callback&response_type=code&scope=https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&state=EUTZF8: 请求中不存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:8300” 访问。

我的问题是

    建议的解决方案是here,唯一的出路吗? Google API 页面上是否有一些我错过的配置? 如果我直接从浏览器直接访问其余 api http://localhost:8300/auth/oauth/test,一切正常。但是,如果我从浏览器向这个 url 发出 get 请求(因为它是安全的,所以应该在身份验证后重定向到 google api,至少应该命中这个 rest api 断点)。因为在这两种情况下,它都可以访问 我的最后一个假设是错误的吗?

如果这是相关的,我正在做有角度的获取请求,例如:

loginWithGoogle()
    console.log(" Login with oauth2 ");
    let oauthUrl = "http://localhost:8300/auth/oauth/test";
    return this.http.get(oauthUrl)                                
      .subscribe(
        res =>                     
          this.onSuccess(res);
        , error => 
          this.onFailure(error);
        );


编辑

实际上,我的第三点是为什么当通过 XHR 从 angular 应用程序访问 rest api 时会抛出 CORS,该应用程序也与 rest api 位于同一域中,而不是当直接从浏览器访问 rest api 时。

【问题讨论】:

你有没有解决过如何避免启动一个新的浏览器窗口?在新的浏览器窗口中打开授权后,我最终得到了回调。 @Spock。不幸的是,没有。 【参考方案1】:

当您使用授权码授权(后端应用程序的 OAuth2 - &response_type=code)时,您必须将浏览器重定向到 /auth 端点 - 您不能为此使用 XHR。用户在认证后会被重定向回来。

重定向到/auth 端点后,用户需要在地址栏中看到该页面来自 Google(可信来源),并且 Google 可能需要进行更多重定向以验证用户身份并显示同意页面.所以使用 XHR 是不可能的。

更新:对于第三点,如果请求不包含有效凭据(不是现在的 HTTP 30x 重定向),您的后端 API 应该返回 HTTP 401。然后,您的 Angular 应用程序需要一个 HTTP 错误处理程序,它将浏览器重定向到 HTTP 401 响应。

但是,如果您想将令牌保留在 Angular 应用程序中,最好使用为在浏览器中运行的应用程序设计的隐式授权。因为使用授权码授权,您的后端具有客户端的角色(在 OAuth2 方案中),但您希望 Angular 应用程序成为客户端(因为它持有令牌)。

【讨论】:

实际上我的第三点是为什么当通过 XHR 从同一域上的角度应用程序访问 rest api 而不是直接从浏览器访问 rest api 时会引发 CORS。 但是,如果您的 XHR 被重定向,它就会到达 Google。如果不是这样,请尝试从浏览器中包含一些日志。如果您的 Angular 应用程序与后端具有相同的来源,那么请求它应该没有 CORS 问题。 无法加载accounts.google.com/o/oauth2/v2/…: 否'Access-Control-Allow-Origin'请求的资源上存在标头。产地'localhost:8300'因此不允许访问。 所以这是我在更新的答案中描述的方式 - XHR 请求被重定向到谷歌,但它应该得到一个 HTTP 401 响应。

以上是关于用于服务器端 Web 应用的 Google Oauth2 的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

低代码如何构建支持OAuth2.0的后端Web API

Cometd vs ActiveMQ 用于实时 Web 应用程序的服务器端推送

在 Chrome 扩展程序中使用 Google 帐户进行服务器端身份验证

未找到 Google 云打印 OAuth 范围

移动端应用迎来WEB时代:Google/Microsoft/Apple已全部支持PWA技术

Google 登录 GoogleIdToken 后端验证突然失败