透過 OAuth 連結帳戶

OAuth 連結類型支援兩種符合業界標準的 OAuth 2.0 流程,分別是隱含授權程式碼流程。

在隱式程式碼流程中,Google 會在使用者的瀏覽器中開啟您的授權端點。成功登入後,系統會將長期存取權杖傳回 Google。從現在起,每次透過 Google 助理傳送給您動作的要求中,都會包含這個存取權杖。

在授權碼流程中,您需要兩個端點:

  • 授權端點,該端點負責將登入 UI 提供給未登入的使用者,並以簡碼授權代碼的形式,記錄使用者要求的存取權。
  • 權杖交換端點,負責以下兩種交換類型:
    1. 交換長期更新權杖的授權碼和短期存取權杖。這項交換作業會在使用者完成帳戶連結流程時進行。
    2. 對短期存取權杖交換交換憑證。當 Google 需要新的存取權杖,因為更新權杖已過期時,就會發生此交換行為。

雖然隱含程式碼流程的實作方式較簡單,但 Google 建議使用隱含流程發布的存取權杖不會過期,因為若權杖與隱含流程搭配使用,就會強制使用者重新連結帳戶。如果基於安全考量而需要權杖過期,您應該考慮改用授權碼流程。

實作 OAuth 帳戶連結

設定專案

如要將專案設為使用 OAuth 連結,請按照下列步驟操作:

  1. 開啟「Actions Console」,然後選取要使用的專案。
  2. 按一下「開發」分頁標籤,然後選擇「帳戶連結」
  3. 啟用「帳戶連結」旁的切換鈕。
  4. 在「建立帳戶」部分中,選取「否,我只想允許在我的網站上建立帳戶」
  5. 在「連結類型」中,選取「OAuth」和「授權碼」

  6. 在「客戶資訊」部分中:

    • 將值指派給「Actions to Google」的用戶端 ID,即可識別來自 Google 的要求。
    • 記下「Google 核發給您動作的用戶端 ID」值;
    • 插入授權和權杖交換端點的網址。
  1. 點按「儲存」

實作 OAuth 伺服器

授權碼流程的 OAuth 2.0 伺服器實作包含兩個端點,您的服務透過 HTTPS 提供。第一個端點是授權端點,負責查找或取得使用者的同意聲明,取得資料存取權。授權端點會向尚未登入的使用者顯示登入使用者介面,並記錄同意所要求的存取權。第二個端點是權杖交換端點,用於取得加密字串 (稱為權杖),以授權動作使用者存取您的服務。

當動作需要呼叫您服務的其中一個 API 時,Google 會一起使用這些端點取得使用者的權限,讓他們代表使用者呼叫這些 API。

Google 發起的 OAuth 2.0 驗證碼流程工作階段如下:

  1. Google 會在使用者的瀏覽器中開啟授權端點。如果在純語音裝置上啟動動作的流程,Google 會將執行作業轉移至手機。
  2. 使用者登入 (如果尚未登入),並授權 Google 在尚未授予權限的情況下透過您的 API 存取其資料。

  3. 您的服務會建立授權碼,並透過將使用者的瀏覽器重新導向回 Google,並提供要求中附加的授權碼,藉此將授權碼傳回 Google。

  4. Google 會將授權碼傳送至您的權杖交換端點,此端點可驗證程式碼的真實性,並傳回存取權杖更新權杖。存取權杖是短期權杖,您的服務可以接受做為存取 API 的憑證。更新權杖是長效權杖,Google 可儲存及用於在新的存取權杖過期時取得該權杖。

  5. 使用者完成帳戶連結流程後,每個從 Google 助理傳送至執行要求 Webhook 的後續要求都會包含一個存取權杖。

處理授權要求

當您的動作需要透過 OAuth 2.0 授權碼流程執行帳戶連結時,Google 會透過包含下列參數的要求將使用者導向授權端點:

授權端點參數
client_id 您在 Google 註冊的 Google 用戶端 ID。
redirect_uri 您將回應傳送至此要求的網址。
state 傳遞至 Google 的簿記值在重新導向 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 的 Google 用戶端 ID 相符,且 redirect_uri 與您為服務提供的重新導向網址相符。這些檢查至關重要,是防止系統授予意外或設定錯誤用戶端應用程式的存取權。

    如果您支援多個 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 Console「專案設定」頁面中的 ID。

  5. 將使用者的瀏覽器重新導向至 redirect_uri 參數指定的網址。請在重新導向時加上 codestate 參數,加入您剛產生的授權碼和原始未經修改的狀態值。以下是結果網址範例:

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

處理權杖交換要求

您的服務權杖交換端點會負責處理兩種權杖交換:

  • 交換存取權杖和更新權杖的授權碼
  • 交換存取權杖的更新權杖

權杖交換要求包含下列參數:

權杖交換端點參數
client_id 用來識別要求來源為 Google 的字串。這個字串必須在系統內註冊為 Google 的專屬 ID。
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. 如果無法確認上述所有條件,就會傳回 HTTP 400 Bad Request 錯誤,且主體為 {"error": "invalid_grant"}
  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. 如果無法確認上述所有條件,就會傳回 HTTP 400 Bad Request 錯誤,且主體為 {"error": "invalid_grant"}
  4. 否則,請使用更新憑證中的使用者 ID 產生存取權杖。這些權杖可以是任何字串值,但權杖必須專門代表使用者和用戶端,且不得猜測。針對存取權杖,請一併記錄權杖的到期時間 (通常是發出權杖後的一小時)。
  5. 在 HTTPS 回應的主體中傳回下列 JSON 物件:
    {
    "token_type": "Bearer",
    "access_token": "ACCESS_TOKEN",
    "expires_in": SECONDS_TO_EXPIRATION
    }

設計驗證流程的語音使用者介面

檢查使用者是否已通過驗證,並啟動帳戶連結流程

  1. Actions 主控台中開啟 Actions Builder 專案。
  2. 建立新的場景,以便在動作中開始連結帳戶:
    1. 按一下「Scenes」
    2. 按一下「add」圖示 (+) 即可新增場景。
  3. 在新建立的場景中,按一下「Conditions」(條件) 圖示
  4. 新增條件,檢查與對話相關聯的使用者是否為已驗證的使用者。如果檢查失敗,您的動作就無法在對話期間執行帳戶連結,而是應改回提供不需要帳戶連結的功能。
    1. 在「Condition」(條件) 下方的 Enter new expression 欄位中,輸入下列邏輯:user.verificationStatus != "VERIFIED"
    2. 在「轉換」下方,選取不需要連結帳戶的場景,或不需要訪客專屬功能的進入點。

  1. 按一下「條件」的「新增」圖示
  2. 新增條件,在使用者沒有相關聯的身分時觸發帳戶連結流程。
    1. 在「Condition」(條件) 下方的 Enter new expression 欄位中,輸入下列邏輯:user.verificationStatus == "VERIFIED"
    2. 在「轉換」下方,選取「帳戶連結」系統場景。
    3. 點按「儲存」

儲存後,名為 <SceneName>_AccountLinking 的帳戶連結系統場景就會新增至專案中。

自訂帳戶連結情境

  1. 在「場景」下方,選取帳戶連結系統場景。
  2. 按一下「Send 提示」,然後新增簡短句子,說明動作需要存取其身分的原因 (例如「如要儲存偏好設定」)。
  3. 點按「儲存」

  1. 在「條件」下方,按一下「如果使用者成功完成帳戶連結」
  2. 設定使用者同意連結帳戶時,流程的後續步驟。 舉例來說,呼叫 Webhook 以處理任何所需的自訂商業邏輯,然後切換回原始場景。
  3. 點按「儲存」

  1. 在「條件」下方,按一下「如果使用者取消或關閉帳戶連結」
  2. 如果使用者不同意連結帳戶,請設定流程。例如,傳送已確認的訊息,然後重新導向至提供不需要連結帳戶的功能的場景。
  3. 點按「儲存」

  1. 在「條件」下方,按一下「如果發生系統或網路錯誤」
  2. 設定若帳戶連結流程因系統或網路錯誤而無法順利完成時,流程該如何繼續。 例如,傳送已確認的訊息,然後重新導向至提供不需要連結帳戶的功能的場景。
  3. 點按「儲存」

處理資料存取要求

如果 Google 助理要求包含存取權杖,請先檢查存取權杖是否有效 (且未過期),然後從資料庫中擷取相關聯的使用者帳戶。