Привязка аккаунта с помощью OAuth

Тип связи OAuth поддерживает два стандартных потока OAuth 2.0: неявный поток и поток кода авторизации .

In the implicit code flow, Google opens your authorization endpoint in the user's browser. After successful sign in, you return a long-lived access token to Google. This access token is now included in every request sent from the Assistant to your Action.

In the authorization code flow, you need two endpoints:

  • The authorization endpoint, which is responsible for presenting the sign-in UI to your users that aren't already signed in and recording consent to the requested access in the form of a short-lived authorization code.
  • The token exchange endpoint, which is responsible for two types of exchanges:
    1. Exchanges an authorization code for a long-lived refresh token and a short-lived access token. This exchange happens when the user goes through the account linking flow.
    2. Exchanges a long-lived refresh token for a short-lived access token. This exchange happens when Google needs a new access token because the one it had expired.

Although the implicit code flow is simpler to implement, Google recommends that access tokens issued using the implicit flow never expire, because using token expiration with the implicit flow forces the user to link their account again. If you need token expiration for security reasons, you should strongly consider using the auth code flow instead.

Реализуйте привязку учетных записей OAuth.

Настроить проект

Чтобы настроить проект для использования связи OAuth, выполните следующие действия:

  1. Откройте консоль действий и выберите проект, который вы хотите использовать.
  2. Откройте вкладку «Разработка» и выберите «Связывание учетной записи» .
  3. Включите переключатель рядом с пунктом «Привязка учетной записи» .
  4. В разделе «Создание учетной записи » выберите «Нет, я хочу разрешить создание учетной записи только на своем веб-сайте ».
  5. В поле «Тип связи» выберите OAuth и «Код авторизации» .

  6. В информации о клиенте :

    • Присвойте значение идентификатору клиента, выданному вашими действиями Google, чтобы идентифицировать запросы, поступающие от Google.
    • Обратите внимание на значение идентификатора клиента, присвоенного Google вашим действиям ;
    • Вставьте URL-адреса конечных точек авторизации и обмена токенами.
  1. Нажмите Сохранить .

Внедрите свой сервер OAuth

授权代码流程的 OAuth 2.0 服务器实现包含两个端点,您的服务通过 HTTPS 提供这些端点。第一个端点是授权端点,负责就数据访问征求用户意见或征求用户意见。授权端点会向尚未登录的用户呈现登录界面,并记录对于请求的访问权限。第二个端点是令牌交换端点,该端点用于获取加密字符串(称为令牌),用于授权 Action 用户访问您的服务。

当您的 Action 需要调用服务的某个 API 时,Google 会同时使用这些端点从用户处获取权限,以代表他们调用这些 API。

由 Google 发起的 OAuth 2.0 授权代码流程会话具有以下流程:

  1. Google 会在用户的浏览器中打开您的授权端点。如果针对 Action 的流程在纯语音设备上开始,Google 会将执行传输到手机。
  2. 用户登录(如果尚未登录),并向 Google 授予使用您的 API 访问其数据的权限(如果他们尚未授予权限)。

  3. 您的服务会创建授权代码,并将用户的浏览器重定向回 Google,并将授权代码附加到请求,从而将其返回给 Google。

  4. Google 会将授权代码发送到您的令牌交换端点,该端点会验证代码的真实性并返回访问令牌刷新令牌。访问令牌是短期有效的令牌,您的服务可接受该令牌作为访问 API 的凭据。刷新令牌是一个长期令牌,Google 可以存储该令牌,并在令牌过期时用它来获取新的访问令牌。

  5. 用户完成帐号关联流程后,从 Google 助理发送到您的执行方式网络钩子的每个后续请求都会包含访问令牌。

处理授权请求

当您的 Action 需要通过 OAuth 2.0 授权代码流程执行帐号关联时,Google 会通过包含以下参数的请求将用户发送到您的授权端点:

授权端点参数
client_id 您向 Google 注册的 Google 客户端 ID。
redirect_uri 您要将该请求的响应发送到的网址。
state 在重定向 URI 中原封不动地传回 Google 的簿记值。
scope 可选:一组用空格分隔的范围字符串,用于指定 Google 请求授权的数据。
response_type 字符串 code

例如,如果您的授权端点位于 https://myservice.example.com/auth,请求可能如下所示:

GET https://myservice.example.com/auth?client_id=GOOGLE_CLIENT_ID&redirect_uri=REDIRECT_URI&state=STATE_STRING&scope=REQUESTED_SCOPES&response_type=code

为了让授权端点能够处理登录请求,请执行以下步骤:

  1. 验证 client_id 与您向 Google 注册的 Google 客户端 ID 是否匹配,以及 redirect_uri 是否与 Google 为您的服务提供的重定向网址匹配。这些检查对于防止授予对意外或配置错误的客户端应用的访问权限非常重要。

    如果您支持多个 OAuth 2.0 流程,另请确认 response_typecode

  2. 检查用户是否登录了您的服务。如果用户没有登录,请完成服务的登录或注册流程。

  3. 生成 Google 用于访问您的 API 的授权代码。授权代码可以是任何字符串值,但它必须唯一地表示用户、令牌的客户端和代码的到期时间,并且必须不可猜测。您通常会签发大约 10 分钟后失效的授权代码。

  4. 确认 redirect_uri 参数指定的网址采用以下格式:

    https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID
    YOUR_PROJECT_ID 是在 Actions 控制台的 Project settings 页面上找到的 ID。

  5. 将用户浏览器重定向到 redirect_uri 参数指定的网址。通过附加 codestate 参数进行重定向时,请添加您刚刚生成的授权代码以及未经修改的原始状态值。以下是生成的网址的示例:

    https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID?code=AUTHORIZATION_CODE&state=STATE_STRING

处理令牌交换请求

您的服务的令牌交换端点负责两种令牌交换:

  • 将授权代码换成访问令牌和刷新令牌
  • 将刷新令牌交换为访问令牌

令牌交换请求包含以下参数:

令牌交换端点参数
client_id 将请求来源标识为 Google 的字符串。该字符串必须在您的系统中注册为 Google 的唯一标识符。
client_secret 您为服务向 Google 注册的密钥字符串。
grant_type 要交换的令牌的类型。可以选择 authorization_coderefresh_token
code 当为 grant_type=authorization_code 时,Google 从您的登录端点或令牌交换端点收到的代码。
redirect_uri 如果此参数为 grant_type=authorization_code,则此参数是在初始授权请求中使用的网址。
refresh_token 如果为 grant_type=refresh_token,则表示 Google 从令牌交换端点收到的刷新令牌。
将授权代码换成访问令牌和刷新令牌

用户登录后,您的授权端点向 Google 返回短期有效的授权代码后,Google 会向令牌交换端点发送请求,以用授权代码换取访问令牌和刷新令牌。

对于这些请求,grant_type 的值为 authorization_codecode 的值为您之前授予 Google 的授权代码的值。以下示例展示了用授权代码交换访问令牌和刷新令牌的请求:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI

为了用访问令牌和刷新令牌交换授权代码,令牌交换端点会响应执行以下步骤的 POST 请求:

  1. 验证 client_id 是否将请求来源标识为已获授权的来源,以及 client_secret 是否与预期值匹配。
  2. 请验证以下内容:
    • 授权代码有效且未过期,并且请求中指定的客户端 ID 与授权代码关联的客户端 ID 一致。
    • redirect_uri 参数指定的网址与初始授权请求中使用的值相同。
  3. 如果您无法验证上述所有条件,则返回正文为 {"error": "invalid_grant"} 的 HTTP 400 Bad Request 错误。
  4. 否则,使用授权代码中的用户 ID 生成刷新令牌和访问令牌。这些令牌可以是任何字符串值,但必须唯一地代表用户和令牌所面向的客户端,并且不得被猜到。对于访问令牌,还要记录令牌的到期时间(通常在令牌颁发一小时后)。刷新令牌不会过期。
  5. 在 HTTPS 响应的正文中返回以下 JSON 对象:
    {
    "token_type": "Bearer",
    "access_token": "ACCESS_TOKEN",
    "refresh_token": "REFRESH_TOKEN",
    "expires_in": SECONDS_TO_EXPIRATION
    }
    

Google 会存储用户的访问令牌和刷新令牌,并记录访问令牌的失效时间。访问令牌到期后,Google 会使用刷新令牌从您的令牌交换端点获取新的访问令牌。

将刷新令牌交换为访问令牌

访问令牌到期后,Google 会向令牌交换端点发送请求,以用刷新令牌换取新的访问令牌。

对于这些请求,grant_type 的值为 refresh_tokenrefresh_token 的值为您之前授予 Google 的刷新令牌的值。以下示例展示了将刷新令牌交换为访问令牌的请求:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

为了用刷新令牌换取访问令牌,令牌交换端点会响应执行以下步骤的 POST 请求:

  1. 验证 client_id 是否将请求来源标识为 Google,以及 client_secret 是否与预期值匹配。
  2. 验证刷新令牌是否有效,以及请求中指定的客户端 ID 是否与与刷新令牌关联的客户端 ID 匹配。
  3. 如果您无法验证上述所有条件,则返回正文为 {"error": "invalid_grant"} 的 HTTP 400 Bad Request 错误。
  4. 否则,请使用刷新令牌中的用户 ID 生成访问令牌。这些令牌可以是任何字符串值,但必须唯一地代表用户和令牌所面向的客户端,并且不得被猜到。对于访问令牌,还要记录令牌的到期时间(通常在令牌颁发一小时后)。
  5. 在 HTTPS 响应的正文中返回以下 JSON 对象:
    {
    "token_type": "Bearer",
    "access_token": "ACCESS_TOKEN",
    "expires_in": SECONDS_TO_EXPIRATION
    }

Разработайте голосовой пользовательский интерфейс для процесса аутентификации.

Проверьте, подтвержден ли пользователь, и запустите процесс привязки учетной записи.

  1. Откройте проект Actions Builder в консоли Actions .
  2. Создайте новую сцену, чтобы начать привязку учетной записи в своем действии:
    1. Нажмите «Сцены» .
    2. Нажмите значок добавления (+), чтобы добавить новую сцену.
  3. Во вновь созданной сцене щелкните значок « для «Условия» .
  4. Добавьте условие, которое проверяет, является ли пользователь, связанный с беседой, проверенным пользователем. Если проверка не пройдена, ваше действие не сможет выполнить привязку учетной записи во время разговора и должно вернуться к предоставлению доступа к функциям, которые не требуют привязки учетной записи.
    1. В поле Enter new expression в разделе «Условие» введите следующую логику: user.verificationStatus != "VERIFIED"
    2. В разделе «Переход» выберите сцену, которая не требует привязки учетной записи, или сцену, которая является точкой входа в функции, доступные только для гостей.

  1. Нажмите значок « для «Условия» .
  2. Добавьте условие для запуска процесса связывания учетной записи, если у пользователя нет связанного удостоверения.
    1. В поле Enter new expression в разделе «Условие » введите следующую логику: user.verificationStatus == "VERIFIED"
    2. В разделе «Переход» выберите системную сцену «Связывание учетных записей» .
    3. Нажмите Сохранить .

После сохранения в ваш проект добавляется новая сцена системы связывания учетных записей под названием <SceneName>_AccountLinking .

Настройте сцену привязки учетной записи

  1. В разделе «Сцены» выберите сцену системы привязки учетной записи.
  2. Нажмите «Отправить запрос» и добавьте короткое предложение, описывающее пользователю, почему Действию необходим доступ к его личности (например, «Чтобы сохранить ваши настройки»).
  3. Нажмите Сохранить .

  1. В разделе «Условия» нажмите «Если пользователь успешно завершил привязку учетной записи» .
  2. Настройте, как должен действовать поток, если пользователь соглашается связать свою учетную запись. Например, вызовите веб-перехватчик для обработки любой необходимой пользовательской бизнес-логики и возврата к исходной сцене.
  3. Нажмите Сохранить .

  1. В разделе «Условия» выберите «Если пользователь отменяет или отклоняет привязку учетной записи» .
  2. Настройте порядок действий, если пользователь не согласен связать свою учетную запись. Например, отправьте подтверждающее сообщение и перенаправьте на сцены, которые предоставляют функциональные возможности, не требующие привязки учетной записи.
  3. Нажмите Сохранить .

  1. В разделе «Условия» выберите «При возникновении системной или сетевой ошибки» .
  2. Настройте, как должен действовать процесс, если процесс связывания учетных записей не может быть завершен из-за системных или сетевых ошибок. Например, отправьте подтверждающее сообщение и перенаправьте на сцены, которые предоставляют функциональные возможности, не требующие привязки учетной записи.
  3. Нажмите Сохранить .

Обработка запросов на доступ к данным

Если запрос Ассистента содержит токен доступа , сначала убедитесь, что токен доступа действителен (и не истек), а затем извлеките связанную учетную запись пользователя из своей базы данных.