OAuth를 사용한 계정 연결

OAuth 연결 유형은 두 가지 업계 표준 OAuth 2.0 흐름, 즉 암시적승인 코드 흐름을 지원합니다.

암시적 코드 흐름에서 Google은 사용자의 브라우저에서 승인 엔드포인트를 엽니다. 로그인에 성공하면 수명이 긴 액세스 토큰을 Google에 반환합니다. 이제 어시스턴트에서 작업으로 전송되는 모든 요청에 이 액세스 토큰이 포함됩니다.

승인 코드 흐름에는 두 개의 엔드포인트가 필요합니다.

  • 승인 엔드포인트: 아직 로그인하지 않은 사용자에게 로그인 UI를 표시하고 요청한 액세스에 대한 동의를 단기 승인 코드 형식으로 기록하는 역할을 합니다.
  • 두 가지 유형의 교환을 담당하는 토큰 교환 엔드포인트:
    1. 장기 갱신 토큰과 단기 액세스 토큰으로 승인 코드를 교환합니다. 이 교환은 사용자가 계정 연결 흐름을 진행할 때 이루어집니다.
    2. 장기 갱신 토큰을 단기 액세스 토큰으로 교환합니다. 이 교환은 액세스 토큰이 만료되어 Google에 새 액세스 토큰이 필요할 때 발생합니다.

암시적 코드 흐름을 구현하는 것이 더 간단하지만 암시적 흐름을 사용하여 발급된 액세스 토큰은 만료되지 않는 것이 좋습니다. 토큰 만료를 암시적 흐름과 함께 사용하면 사용자가 계정을 다시 연결하게 되기 때문입니다. 보안상의 이유로 토큰 만료가 필요하다면 인증 코드 흐름을 대신 사용하는 것이 좋습니다.

OAuth 계정 연결 구현

프로젝트 구성

OAuth 연결을 사용하도록 프로젝트를 구성하려면 다음 단계를 따르세요.

  1. Actions Console을 열고 사용할 프로젝트를 선택합니다.
  2. 개발 탭을 클릭하고 계정 연결을 선택합니다.
  3. 계정 연결 옆에 있는 스위치를 사용 설정합니다.
  4. 계정 생성 섹션에서 아니요, 내 웹사이트에서만 계정 생성을 허용하고 싶습니다를 선택합니다.
  5. 연결 유형에서 OAuth승인 코드를 선택합니다.

  6. 클라이언트 정보:

    • Actions에서 Google에 발행한 클라이언트 ID에 값을 할당하여 Google에서 수신되는 요청을 식별합니다.
    • Google에서 작업에 발급한 클라이언트 ID의 값을 기록해 둡니다.
    • 승인 및 토큰 교환 엔드포인트의 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 助理发送到您的 fulfillment webhook 的请求包含 访问令牌。

处理授权请求

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

授权端点参数
client_id 您在 Google 注册的 Google 客户端 ID。
redirect_uri 此请求的响应发送到的网址。
state 将一个在 重定向 URI。
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 客户端 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项目设置页面上的 ID Actions 控制台界面。

  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 就会向您的令牌交换端点发送请求, 访问令牌和刷新令牌的授权码。

对于这些请求,grant_type 的值为 authorization_code,值 code 是您先前向 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. 请验证以下内容: <ph type="x-smartling-placeholder">
      </ph>
    • 授权代码有效且未过期,且客户端 请求中指定的 ID 与 授权代码。
    • redirect_uri 参数指定的网址完全相同 初始授权请求中使用的值。
  3. 如果您无法验证上述所有条件,则返回 HTTP 正文为 {"error": "invalid_grant"} 的 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_token,值 refresh_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 是否将请求来源标识为 并且 client_secret 与预期 值。
  2. 请确认刷新令牌有效,以及在 请求与刷新令牌所关联的客户端 ID 相匹配。
  3. 如果您无法验证上述所有条件,则返回 HTTP 正文为 {"error": "invalid_grant"} 的 400 Bad Request 错误。
  4. 否则,请使用刷新令牌中的用户 ID 来生成访问权限 令牌。这些标记可以是任何字符串值,但它们必须唯一地表示 令牌对应的用户和客户端,并且不得被猜到。 对于访问令牌,请记录令牌的到期时间 (通常在您发放令牌一小时后)。
  5. 在 HTTPS 的正文中返回以下 JSON 对象 回答:
    {
    "token_type": "不记名",
    "access_token": "ACCESS_TOKEN",
    “expires_in”:SECONDS_TO_EXPIRATION
    }

인증 흐름을 위한 음성 사용자 인터페이스 설계

사용자가 인증되었는지 확인하고 계정 연결 흐름을 시작합니다.

  1. Actions 콘솔에서 Actions Builder 프로젝트를 엽니다.
  2. 작업에서 계정 연결을 시작할 새 장면을 만듭니다.
    1. 장면을 클릭합니다.
    2. add (+) 아이콘을 클릭하여 새 장면을 추가합니다.
  3. 새로 만든 장면에서 조건의 추가 아이콘을 클릭합니다.
  4. 대화와 연결된 사용자가 인증된 사용자인지 확인하는 조건을 추가합니다. 검사에 실패하면 작업이 대화 중에 계정 연결을 실행할 수 없으며 계정 연결이 필요하지 않은 기능에 대한 액세스 권한을 제공하는 것으로 대체됩니다.
    1. 조건Enter new expression 필드에 다음 로직을 입력합니다. user.verificationStatus != "VERIFIED"
    2. Transition에서 계정 연결이 필요하지 않은 장면이나 게스트 전용 기능의 진입점인 장면을 선택합니다.

  1. 조건의 추가 아이콘을 클릭합니다.
  2. 사용자에게 연결된 ID가 없는 경우 계정 연결 흐름을 트리거하는 조건을 추가합니다.
    1. 조건Enter new expression 필드에 다음 로직을 입력합니다. user.verificationStatus == "VERIFIED"
    2. Transition에서 Account Linking 시스템 장면을 선택합니다.
    3. 저장을 클릭합니다.

저장하면 <SceneName>_AccountLinking라는 새 계정 연결 시스템 장면이 프로젝트에 추가됩니다.

계정 연결 장면 맞춤설정

  1. Scenes(장면)에서 계정 연결 시스템 장면을 선택합니다.
  2. 메시지 보내기를 클릭하고 작업에서 사용자 ID에 액세스해야 하는 이유를 설명하는 짧은 문장을 추가합니다 (예: '환경설정 저장').
  3. 저장을 클릭합니다.

  1. 조건에서 사용자가 계정 연결을 완료한 경우를 클릭합니다.
  2. 사용자가 계정 연결에 동의하는 경우 흐름을 어떻게 진행할지 구성합니다. 예를 들어 웹훅을 호출하여 필요한 맞춤 비즈니스 로직을 처리하고 원래 장면으로 다시 전환할 수 있습니다.
  3. 저장을 클릭합니다.

  1. 조건에서 사용자가 계정 연결을 취소하거나 닫은 경우를 클릭합니다.
  2. 사용자가 계정 연결에 동의하지 않는 경우 흐름을 진행하는 방법을 구성합니다. 예를 들어 확인 메시지를 보내고 계정 연결이 필요하지 않은 기능을 제공하는 장면으로 리디렉션합니다.
  3. 저장을 클릭합니다.

  1. 조건에서 시스템 또는 네트워크 오류가 발생한 경우를 클릭합니다.
  2. 시스템 또는 네트워크 오류로 인해 계정 연결 흐름을 완료할 수 없는 경우 흐름을 진행하는 방법을 구성합니다. 예를 들어 확인 메시지를 보내고 계정 연결이 필요하지 않은 기능을 제공하는 장면으로 리디렉션합니다.
  3. 저장을 클릭합니다.

데이터 액세스 요청 처리

Assistant 요청에 액세스 토큰이 포함되어 있으면 먼저 액세스 토큰이 유효하고 만료되지 않았는지 확인한 후 데이터베이스에서 연결된 사용자 계정을 검색합니다.