0

我在使用 Google 助理的 OAuth 隐式流程时遇到问题。我设法设置了一个 OAuth 服务器并让它工作。这是流程:

用户被重定向到我的端点,使用 Google 帐户进行身份验证,并使用访问令牌和结果代码=SUCCES 将其发送回助手。

在我的完成中,我通过向以下地址发出 https 请求来获取用户的电子邮件地址:https://www.googleapis.com/plus/v1/people/me?access_token=access_token

然后我在我的数据库中找到匹配的用户并将访问令牌添加到该用户的数据库中。

下次用户登录时,我会检查访问令牌并用他们的名字问候用户。

现在的问题是这是隐式流,根据文档应该有一个永不过期的访问令牌:

注意:Google 要求使用隐式流发布的访问令牌永不过期,因此您不需要像其他 OAuth 2.0 流那样记录访问令牌的授予时间。

但是助手强迫我每小时重新验证一次,这意味着访问令牌确实过期了。

我的问题是:这个流程是正确的还是我错过了什么?我在 OAuth 端点中做错了什么吗?

我的端点基于https://developers.google.com/identity/protocols/OAuth2UserAgent

<html>

  <head>
    <script src="https://apis.google.com/js/platform.js" async defer></script>
    <meta name="google-signin-client_id" content="CLIENT_ID">
  </head>

  <body>
    <script>
      var YOUR_CLIENT_ID = 'CLIENT_ID';

    function oauth2SignIn() {
        // Google's OAuth 2.0 endpoint for requesting an access token
        var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

        // Create element to open OAuth 2.0 endpoint in new window.
        var form = document.createElement('form');
        form.setAttribute('method', 'GET'); // Send as a GET request.
        form.setAttribute('action', oauth2Endpoint);

        //Get the state and redirect_uri parameters from the request
        var searchParams = new URLSearchParams(window.location.search);
        var state = searchParams.get("state");
        var redirect_uri = searchParams.get("redirect_uri");
        //var client_id = searchParams.get("client_id");

        // Parameters to pass to OAuth 2.0 endpoint.
        var params = {
          'client_id': YOUR_CLIENT_ID,
          'redirect_uri': redirect_uri,
          'scope': 'email',
          'state': state,
          'response_type': 'token',
          'include_granted_scopes': 'true'
        };

        // Add form parameters as hidden input values.
        for (var p in params) {
          var input = document.createElement('input');
          input.setAttribute('type', 'hidden');
          input.setAttribute('name', p);
          input.setAttribute('value', params[p]);
          form.appendChild(input);
        }

        // Add form to page and submit it to open the OAuth 2.0 endpoint.
        document.body.appendChild(form);
        form.submit();
      }
  oauth2SignIn();
    </script>
  </body>

  </html>
4

1 回答 1

2

听起来您正在做的是让用户登录您的页面,并使用它从 Google 服务获取身份验证令牌。然后,您将其转过来并将其传回给助手,并将其称为身份流。

虽然很聪明——这不是身份流程。

这是您使用身份验证代码流向 Google 验证用户身份,然后将此令牌返回给 Google 并假装这是身份流令牌。但是,由于您使用的是身份验证代码流,因此您取回的身份验证令牌会在一小时后过期。(您可以在从 Google 返回的信息中查看生命周期。)

如果您尝试进行帐户链接而不自己管理任何内容,则需要实际实现一个 OAuth 服务器,该服务器代理从 Google 助理到 Google 的 Auth Code Flow 请求以及从 Google 返回到 Google 助理的回复。虽然可行,但这可能违反了他们的政策,并且通常不建议这样做。

更新以解决您评论中的一些问题/问题。

使用 Google Auth 端点也不会存储会话,因此您仍然需要每小时重新进行身份验证

由于 Google 身份验证端点使用身份验证代码流,因此您可以使用该offline模式来请求刷新令牌。然后,当授权令牌过期时,您可以使用刷新令牌获取新的授权令牌。所以你仍然有一个长期的访问授权,并且可以获得短期令牌来做你需要的工作。

然而,试图将其硬塞到身份流中是行不通的。(即使确实如此,这也是一个非常糟糕的主意。)

您能否就如何为隐式流创建端点提供一些说明?

除了在 Assistant 文档中逐步描述OAuth 服务器代码可以做什么之外,我不确定您需要什么说明。您的 OAuth 服务器基本上只需要:

  • 能够拥有一个用户:
    • 连接到 HTTPS URL
    • 验证自己
    • 授权 Google 助理代表他们联系您的服务
  • 通过使用参数中的代码将用户重定向到 Google 的 URL 来返回代码

Action webhook 需要能够:

  • 接受此代码作为 Google 助理请求的一部分,然后
  • 从这段代码中找出用户是谁。(即 - 将代码映射到系统中的用户帐户。)

您可以通过多种方式完成所有这些工作。OAuth 服务器和 Action 可以在同一台服务器上或分开,但他们至少需要就该代码是什么以及如何映射到您的用户帐户达成一些协议。

如果您的主要需求是代表您的用户访问 Google API,那么您拥有的用户帐户可能会存储用于访问 Google 服务器的 OAuth 令牌。但您应该从逻辑上将其与 Google 助理用来访问您的服务器的代码分开。

(顺便说一句,这些步骤是针对身份流程的。身份验证代码流程还有几个步骤,但基本原理是相似的。尤其是在操作方面。)

于 2017-11-09T14:17:10.443 回答