每個 smart home 動作都必須包含驗證使用者的機制。
驗證機制可讓您將使用者的 Google 帳戶連結至驗證系統中的使用者帳戶。如此一來,當您的執行要求收到智慧型住宅意圖時,就能辨識使用者。Google 智慧型住宅僅支援含有授權碼流程的 OAuth。
本頁說明如何設定 OAuth 2.0 伺服器,以便與 smart home 動作搭配使用。
使用 OAuth 連結 Google 帳戶
在授權碼流程中,您需要兩個端點:
授權端點,會向登入的使用者顯示登入使用者介面。授權端點也會建立一個臨時的授權碼,記錄使用者對要求存取權的同意。
權杖交換端點,負責以下兩種交換類型:
- 交換長期更新權杖的授權碼和短期存取權杖。這項交換作業會在使用者完成帳戶連結流程時進行,
- 交換短期存取權杖的長期更新權杖。當 Google 因為新的存取權杖已過期而需要新存取權杖時,就會進行此交換作業。
設計指南
本節說明您代管 OAuth 連結流程的使用者畫面設計需求和建議。Google 應用程式呼叫這個平台後,您的平台會向使用者顯示登入 Google 頁面和帳戶連結同意畫面。獲得使用者同意連結帳戶後,系統會將使用者導回 Google 的應用程式。

需求條件
- 您必須告知使用者的帳戶將連結至 Google,而非 Google Home 或 Google 助理等特定 Google 產品。
- 您必須取得 Google 授權聲明,例如「登入帳戶後,授權 Google 控制您的裝置」。請參閱 Google Home 開發人員政策的 Google Device Policy 授權部分。
最佳化建議
建議您採取下列做法:
顯示 Google 隱私權政策。在同意畫面中加入 Google 隱私權政策連結。
分享的資料。使用簡明扼要的語言,向使用者說明 Google 需要哪些資料,以及原因。
使用明確的行動號召。在同意畫面上顯示清楚的行動號召,例如「同意並連結」。這是因為使用者需要知道,Google 需要哪些資料才能連結帳戶。
可取消。讓使用者可以選擇不要返回,或是取消連結。
清除登入程序。請確保使用者能夠明確登入 Google 帳戶,例如使用者名稱和密碼的欄位或「使用 Google 帳戶登入」。
取消連結功能。提供一種使用者可以取消連結的機制,例如平台中帳戶設定頁面的網址。或者,您也可以加入 Google 帳戶連結,方便使用者管理已連結帳戶。
可變更使用者帳戶。建議使用者切換帳戶。如果使用者通常有多個帳戶,這項功能特別有用。
- 如果使用者必須關閉同意畫面才能切換帳戶,請將可復原的錯誤傳送給 Google,讓使用者可以使用 OAuth 連結登入想要的帳戶。
加入標誌。在同意畫面上顯示您的公司標誌。 使用樣式規範設定標誌。如要顯示 Google 的標誌,請參閱標誌和商標。

授權碼流程
「授權碼」流程的 OAuth 2.0 伺服器實作包含兩個端點,您的服務可透過 HTTPS 提供。第一個端點是授權端點,負責尋找及存取資料,或取得使用者同意聲明。授權端點會將登入使用者介面提供給尚未登入的使用者,並記錄同意要求的存取權。第二個端點是權杖交換端點,可用於取得加密字串 (稱為「權杖」),授權使用者存取服務。
當 Google 應用程式需要呼叫您其中一個服務的 API 時,Google 會同時使用這些端點,取得您使用者授權來呼叫這些 API 的權限。
Google 發起的 OAuth 2.0 授權碼流程流程如下:
- Google 會在使用者的瀏覽器中開啟授權端點。如果流程是在語音專用裝置上執行動作,Google 會將執行作業轉移到手機。
- 如果使用者尚未登入,系統會登入,並授予 Google 透過您的 API 存取其資料的權限;如果使用者尚未授予權限,則會授權 Google。
- 您的服務會建立授權碼,然後傳送給 Google。如要執行此操作,請將使用者瀏覽器重新導向至 Google,並在要求中附上授權碼。
- Google 會將授權碼傳送至您的權杖交換端點,這個程式碼會驗證程式碼的真實性,並傳回存取權杖和更新權杖。存取權杖是一種短期權杖,讓您的服務接受以存取 API 的憑證。更新權杖是一種長期權杖,當 Google 到期時,Google 可以用來儲存新的存取權杖。
- 使用者完成帳戶連結流程後,Google 傳送的所有後續要求都含有存取權杖。
處理授權要求
如果您需要使用 OAuth 2.0 授權碼流程執行帳戶連結,Google 會傳送要求到授權端點,其中包含包含下列參數的要求:
授權端點參數 | |
---|---|
client_id |
您指派給 Google 的用戶端 ID。 |
redirect_uri |
將回應傳送至這個請求的網址。 |
state |
將傳回 Google 的記帳值在重新導向 URI 中維持不變。 |
scope |
選用:以空格分隔的一組範圍字串,用於指定 Google 要求授權的資料。 |
response_type |
回應中要傳回的值類型。如果是 OAuth 2.0 授權流程流程,回應類型一律為 code 。 |
user_locale |
採用 RFC5646 格式的 Google 帳戶語言設定,以便讓使用者以偏好的語言將內容本地化。 |
例如,如果您的授權端點位於 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&user_locale=LOCALE
為了讓授權端點處理登入要求,請按照下列步驟操作:
- 驗證
client_id
與指派給 Google 的用戶端 ID 相符,且redirect_uri
與 Google 為您的服務提供的重新導向網址相符。這類檢查作業可防止他人存取非預期或設定錯誤的用戶端應用程式。如果您支援多個 OAuth 2.0 流程,請確認response_type
為code
。 - 檢查使用者是否已登入服務。如果使用者未登入,請完成服務的登入或註冊流程。
- 產生授權碼,讓 Google 存取您的 API。授權碼可以是任何字串值,但必須代表使用者、權杖所屬的用戶端和代碼的到期時間,且不得猜測。系統通常會提供大約 10 分鐘後到期的授權碼。
- 確認
redirect_uri
參數指定的網址格式如下:https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID https://oauth-redirect-sandbox.googleusercontent.com/r/YOUR_PROJECT_ID
- 將使用者的瀏覽器重新導向至
redirect_uri
參數指定的網址。附上code
和state
參數,在重新導向時加上您剛剛產生的授權碼及原始的未修改狀態值。以下是結果網址的範例:https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID?code=AUTHORIZATION_CODE&state=STATE_STRING
處理權杖交換要求
您的服務權杖交換端點會負責兩種權杖交換作業:
- 取得存取權杖和更新權杖的授權碼
- 交換存取權杖的更新權杖
權杖交換要求包含下列參數:
權杖交換端點參數 | |
---|---|
client_id |
可識別要求來源為 Google 的字串。這個字串必須在您的系統中註冊為 Google #39; 專屬 ID。 |
client_secret |
您向 Google 註冊的服務的密鑰字串。 |
grant_type |
交換的權杖類型。該屬性為 authorization_code 或 refresh_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_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
要求:
- 驗證
client_id
是否將要求來源視為授權來源,且client_secret
與預期值相符。 - 確認授權碼是否有效且尚未過期,且要求中指定的用戶端 ID 與與授權碼相關聯的用戶端 ID 相符。
- 確認
redirect_uri
參數指定的網址與初始授權要求中使用的值相同。 - 如果無法驗證上述所有條件,請傳回包含
{"error": "invalid_grant"}
的 HTTP 400 Bad Request 錯誤。 - 否則,請使用授權碼中的使用者 ID 產生重新整理權杖和存取權杖。這些權杖可以是任何字串值,但必須唯一代表使用者和符記的用戶端,且無法猜測。如果是存取權杖,請一併記錄權杖的到期時間 (通常是核發權杖後的一小時)。重新整理權杖不會失效。
- 在 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
要求:
- 驗證
client_id
會將要求來源視為 Google,且client_secret
與預期值相符。 - 確認重新整理權杖有效,且要求中指定的用戶端 ID 與與更新權杖相關聯的用戶端 ID 相符。
- 如果無法驗證上述所有條件,請傳回包含
{"error": "invalid_grant"}
的 HTTP 400 Bad Request 錯誤。 - 否則,請使用更新權杖中的使用者 ID 產生存取權杖。這些權杖可以是任何字串值,但必須唯一代表使用者及權杖的用戶端,且不得有理論。如果是存取權杖,請一併記錄權杖的到期時間 (通常是核發權杖後的一小時)。
- 在 HTTPS 回應的主體中傳回下列 JSON 物件:
{ "token_type": "Bearer","access_token": "ACCESS_TOKEN","expires_in": SECONDS_TO_EXPIRATION }
處理使用者資訊要求
userinfo 端點是受 OAuth 2.0 保護的資源,可傳回與已連結使用者相關的版權聲明。您可以自行決定是否要導入和代管 Userinfo 端點,但下列情況除外:
成功從權杖端點擷取存取權杖後,Google 會向您的使用者資訊端點傳送要求,以擷取連結使用者的基本設定檔資訊。
使用者資訊端點要求標頭 | |
---|---|
Authorization header |
熊類型的存取權杖。 |
例如,如果您的使用者資訊端點位於 https://myservice.example.com/userinfo
,則要求可能如下所示:
GET /userinfo HTTP/1.1 Host: myservice.example.com Authorization: Bearer ACCESS_TOKEN
為您的 Userinfo 端點處理要求的步驟如下:
- 從 Authorization 標頭擷取存取權杖,並傳回與存取權杖相關聯的使用者資訊。
- 如果存取權杖無效,請使用
WWW-Authenticate
回應標頭傳回 HTTP 401 未經授權錯誤。以下是 userinfo 錯誤回應的範例:HTTP/1.1 401 Unauthorized WWW-Authenticate: error="invalid_token", error_description="The Access Token expired"
如果 401 未授權,或者在連結過程中傳回任何其他失敗的錯誤回應,錯誤都將無法復原,系統擷取之後的權杖將被捨棄,使用者必須重新啟動連結程序。 { "sub": "USER_UUID", "email": "EMAIL_ADDRESS", "given_name": "FIRST_NAME", "family_name": "LAST_NAME", "name": "FULL_NAME", "picture": "PROFILE_PICTURE", }
使用者資訊端點回應 sub
可識別您系統中使用者的專屬 ID。 email
使用者的電子郵件地址。 given_name
選用:使用者的名字。 family_name
選用:使用者的姓氏。 name
選用:使用者的全名。 picture
選用:使用者的個人資料相片。