適用於電視和有限輸入裝置應用程式的 OAuth 2.0

這份文件說明如何實作 OAuth 2.0 授權,以便透過在電視、遊戲主機和印表機等裝置上執行的應用程式存取 YouTube Data API。具體來說,這個流程是專為無法存取瀏覽器或輸入功能有限的裝置而設計。

OAuth 2.0 可讓使用者與應用程式共用特定資料,同時保有使用者名稱、密碼和其他資訊的隱私。舉例來說,電視應用程式可以使用 OAuth 2.0 取得權限,以選取儲存在 Google 雲端硬碟中的檔案。

由於使用這個流程的應用程式會分配到個別裝置,因此會假設應用程式不能保存密鑰。當使用者在應用程式進行中或應用程式在背景執行時,這類應用程式就能存取 Google API。

替代方案

如果您要為 Android、iOS、macOS、Linux 或 Windows (包括通用 Windows 平台) 等平台編寫應用程式,且該平台可存取瀏覽器和完整輸入功能,請使用行動和電腦版應用程式的 OAuth 2.0 流程。(即使應用程式是沒有圖形介面的指令列工具,也還是應該使用這個流程)。

如果您「只」想讓使用者透過 Google 帳戶登入,並使用 JWT ID 權杖來取得基本使用者個人資料資訊,請參閱透過電視登入和受限制的輸入裝置

先備知識

為專案啟用 API

凡是呼叫 Google API 的應用程式,都必須在 API Console中啟用這些 API。

如何在專案中啟用 API:

  1. Google API Console中的Open the API Library
  2. If prompted, select a project, or create a new one.
  3. 在「資料庫」頁面中,找出並啟用 YouTube Data API。找出應用程式會使用的任何其他 API,並啟用這些 API。

建立授權憑證

凡是使用 OAuth 2.0 存取 Google API 的應用程式,都必須擁有授權憑證,可供 Google 的 OAuth 2.0 伺服器識別該應用程式。下列步驟說明如何為專案建立憑證。這樣一來,應用程式即可使用憑證存取您為專案啟用的 API。

  1. Go to the Credentials page.
  2. 按一下 [Create credentials] (建立憑證) > [OAuth client ID] (OAuth 用戶端 ID)
  3. 選取「電視和受限制的輸入裝置」應用程式類型。
  4. 為 OAuth 2.0 用戶端命名,然後按一下「建立」

識別存取權範圍

範圍可讓應用程式僅要求存取其所需的資源,也能讓使用者控管他們授予應用程式的存取權量。因此,要求的範圍數量與取得使用者同意聲明的可能性可能存在相反關係。

開始實作 OAuth 2.0 授權之前,建議您找出應用程式需要權限存取的範圍。

YouTube Data API 第 3 版使用下列範圍:

狙擊鏡
https://www.googleapis.com/auth/youtube管理您的 YouTube 帳戶
https://www.googleapis.com/auth/youtube.channel-memberships.creator查看您現有的有效頻道會員清單,以及這些會員目前的級別和成為會員的時間點
https://www.googleapis.com/auth/youtube.force-ssl查看、編輯並永久刪除您的 YouTube 影片、評分、留言和字幕
https://www.googleapis.com/auth/youtube.readonly查看您的 YouTube 帳戶
https://www.googleapis.com/auth/youtube.upload管理您的 YouTube 影片
https://www.googleapis.com/auth/youtubepartner查看及管理您在 YouTube 上的元素和相關內容
https://www.googleapis.com/auth/youtubepartner-channel-audit查看您的 YouTube 頻道中與 YouTube 合作夥伴稽核程序相關的私人資訊

如要查看已安裝的應用程式或裝置,請參閱「允許的範圍」清單。

取得 OAuth 2.0 存取權杖

即使應用程式在輸入功能有限的裝置上執行,使用者還是需要具備輸入功能更豐富的裝置存取權,才能完成這項授權流程。 流程包含以下步驟:

  1. 應用程式會將要求傳送至 Google 的授權伺服器,而該伺服器會指出應用程式要求存取的範圍。
  2. 伺服器回應包含後續步驟中所用的多項資訊,例如裝置代碼和使用者代碼。
  3. 顯示使用者可在其他裝置輸入的資訊,以便授權您的應用程式。
  4. 應用程式會開始輪詢 Google 的授權伺服器,判斷使用者是否授權應用程式。
  5. 使用者切換至輸入功能更豐富的裝置,啟動網路瀏覽器並前往步驟 3 顯示的網址,並輸入在步驟 3 中顯示的代碼。接著,使用者就能授予 (或拒絕) 應用程式存取權。
  6. 輪詢要求的下一個回應包含應用程式必須代表使用者授權要求的憑證。(如果使用者拒絕存取應用程式,回應不會包含權杖)。

下圖說明這個程序:

使用者登入另一部已安裝瀏覽器的裝置

下列各節將詳細說明這些步驟。考量到裝置可能具備的功能和執行階段環境範圍,本文件中的範例使用 curl 指令列公用程式。這些範例必須可輕鬆移植到各種語言和執行階段。

步驟 1:索取裝置和使用者代碼

在這個步驟中,您的裝置會將 HTTP POST 要求傳送至位於 https://oauth2.googleapis.com/device/code 的 Google 授權伺服器,該伺服器可識別您的應用程式,以及應用程式要代表使用者存取的存取權範圍。請使用 device_authorization_endpoint 中繼資料值,從探索文件中擷取這個網址。請加入下列 HTTP 要求參數:

參數
client_id 必要

應用程式的用戶端 ID。您可以在 API Console Credentials page中找到這個值。

scope 必要

以空格分隔的範圍清單,這些範圍會識別應用程式可以代表使用者存取的資源。這些值會通知 Google 向使用者顯示的同意畫面。如要瞭解已安裝應用程式或裝置,請參閱允許的範圍清單。

範圍可讓應用程式僅要求存取所需的資源,也能讓使用者控管他們授予應用程式的存取權量。因此,要求的範圍數量與取得使用者同意聲明的可能性之間存在相反關係。

YouTube Data API 第 3 版使用下列範圍:

狙擊鏡
https://www.googleapis.com/auth/youtube管理您的 YouTube 帳戶
https://www.googleapis.com/auth/youtube.channel-memberships.creator查看您現有的有效頻道會員清單,以及這些會員目前的級別和成為會員的時間點
https://www.googleapis.com/auth/youtube.force-ssl查看、編輯並永久刪除您的 YouTube 影片、評分、留言和字幕
https://www.googleapis.com/auth/youtube.readonly查看您的 YouTube 帳戶
https://www.googleapis.com/auth/youtube.upload管理您的 YouTube 影片
https://www.googleapis.com/auth/youtubepartner查看及管理您在 YouTube 上的元素和相關內容
https://www.googleapis.com/auth/youtubepartner-channel-audit查看您的 YouTube 頻道中與 YouTube 合作夥伴稽核程序相關的私人資訊

OAuth 2.0 API 範圍文件提供完整的範圍清單,可讓您存取 Google API。

示例

下列程式碼片段為要求範例:

POST /device/code HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

client_id=client_id&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly

以下範例顯示了可傳送相同要求的 curl 指令:

curl -d "client_id=client_id&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly" \
     https://oauth2.googleapis.com/device/code

步驟 2:處理授權伺服器回應

授權伺服器會傳回以下其中一個回應:

成功回應

如果要求有效,回應會是含有下列屬性的 JSON 物件:

屬性
device_code Google 會明確指派的值,用於識別執行要求授權的應用程式裝置。使用者將透過另一部裝置,取得更豐富的輸入功能。舉例來說,使用者可能會使用筆記型電腦或手機,授權在電視上執行的應用程式。在此情況下,device_code 會識別電視。

這個程式碼可讓執行應用程式的裝置安全地判斷使用者是否已授予或拒絕存取權。

expires_in device_codeuser_code 有效的時間長度 (以秒為單位)。如果在此期間,使用者未完成授權流程,裝置也不會輪詢以擷取使用者的決定相關資訊,您可能需要從步驟 1 重新開始這項程序。
interval 裝置在輪詢要求之間等待的時間長度 (以秒為單位)。舉例來說,如果值為 5,裝置應每隔五秒鐘傳送輪詢要求至 Google 授權伺服器。詳情請參閱步驟 3
user_code 區分大小寫的值,可向 Google 識別應用程式要求存取的範圍。使用者介面會指示使用者在具備更多輸入功能的獨立裝置上輸入這個值。接著,Google 會在提示使用者授予應用程式存取權時,使用該值顯示正確的範圍組合。
verification_url 使用者必須在其他裝置上前往這個網址才能輸入 user_code,並授予或拒絕應用程式存取權。您的使用者介面也會顯示這個值。

以下程式碼片段為回應範例:

{
  "device_code": "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8",
  "user_code": "GQVQ-JKEC",
  "verification_url": "https://www.google.com/device",
  "expires_in": 1800,
  "interval": 5
}

「超過配額」回應

如果裝置代碼要求超過與用戶端 ID 相關聯的配額,您會收到 403 回應,其中包含以下錯誤:

{
  "error_code": "rate_limit_exceeded"
}

在這種情況下,請使用輪詢策略來降低要求比率。

步驟 3:顯示使用者程式碼

向使用者顯示在步驟 2 中取得的 verification_urluser_code。這兩個值都可以包含 US-ASCII 字元集的任何可列印字元。您向使用者顯示的內容應指示使用者在其他裝置前往 verification_url,並輸入 user_code

設計使用者介面 (UI) 時,請牢記下列規則:

  • user_code
    • user_code 必須在可處理 15「W」大小字元的欄位中顯示。也就是說,如果您可以正確顯示 WWWWWWWWWWWWWWW 程式碼,就表示您的 UI 有效,建議您在測試 user_code 顯示 UI 的方式時使用此字串值。
    • user_code 區分大小寫,請勿以任何方式修改,例如變更大小寫或插入其他格式設定字元。
  • verification_url
    • 顯示 verification_url 的空間必須夠寬,才能處理長度為 40 個字元的網址字串。
    • 請勿以任何方式修改 verification_url,除非是選擇性移除顯示配置。如果您因為顯示原因而打算從網址中移除配置 (例如 https://),請確認應用程式可以同時處理 httphttps 變化版本。

步驟 4:輪詢 Google 的授權伺服器

由於使用者將透過另一部裝置前往 verification_url 並授予 (或拒絕) 存取權,因此當使用者回應存取要求時,要求的裝置不會自動收到通知。因此,提出要求的裝置需要輪詢 Google 的授權伺服器,才能判斷使用者何時回應要求。

提出要求的裝置應繼續傳送輪詢要求,直到收到回應指出使用者已回應存取要求,或直到 步驟 2 中取得的 device_codeuser_code 過期為止。步驟 2 中傳回的 interval 指定要求之間等待的時間長度 (以秒為單位)。

要輪詢的端點網址為 https://oauth2.googleapis.com/token。輪詢要求包含下列參數:

參數
client_id 應用程式的用戶端 ID。您可以在 API Console Credentials page中找到這個值。
client_secret 所提供 client_id 的用戶端密鑰。您可以在 API Console Credentials page中找到這個值。
device_code 步驟 2 中授權伺服器傳回的 device_code
grant_type 將值設為 urn:ietf:params:oauth:grant-type:device_code

示例

下列程式碼片段為要求範例:

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

client_id=client_id&
client_secret=client_secret&
device_code=device_code&
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code

以下範例顯示了可傳送相同要求的 curl 指令:

curl -d "client_id=client_id&client_secret=client_secret& \
         device_code=device_code& \
         grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code" \
         -H "Content-Type: application/x-www-form-urlencoded" \
         https://oauth2.googleapis.com/token

步驟 5:使用者回應存取權要求

下圖顯示了與使用者前往步驟 3 顯示的 verification_url 時看到的內容:

輸入代碼以連結裝置

進入 user_code 後,如果尚未登入 Google,使用者就會看到如下圖所示的同意畫面:

裝置用戶端同意畫面範例

步驟 6:處理輪詢要求的回應

Google 的授權伺服器會使用以下其中一種回應來回應每個輪詢要求:

已獲得存取權

如果使用者授予裝置存取權 (透過點選同意畫面上的 Allow 的方式),回應就會包含存取權杖和更新權杖。讓您的裝置能夠代表使用者存取 Google API。(回應中的 scope 屬性會決定裝置可以存取的 API)。

在此情況下,API 回應包含下列欄位:

欄位
access_token 您的應用程式為授權 Google API 要求而傳送的憑證。
expires_in 存取權杖的剩餘生命週期 (以秒為單位)。
refresh_token 可用來取得新的存取權杖的憑證。重新整理權杖會持續有效,直到使用者撤銷存取權為止。請注意,系統一律會針對裝置傳回重新整理權杖。
scope access_token 授予的存取權範圍,以空格分隔且區分大小寫的字串清單表示。
token_type 傳回的權杖類型。目前,這個欄位的值一律會設為 Bearer

以下程式碼片段為回應範例:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
  "token_type": "Bearer",
  "refresh_token": "1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

存取權杖的生命週期有限。如果應用程式需要長期存取 API,可以使用更新權杖取得新的存取權杖。如果您的應用程式需要這類型的存取權,則應儲存更新權杖供日後使用。

存取遭拒

如果使用者拒絕授予裝置存取權,則伺服器回應會傳回 403 HTTP 回應狀態碼 (Forbidden)。回應會包含下列錯誤:

{
  "error": "access_denied",
  "error_description": "Forbidden"
}

待授權

如果使用者尚未完成授權流程,伺服器會傳回 428 HTTP 回應狀態碼 (Precondition Required)。回應包含下列錯誤:

{
  "error": "authorization_pending",
  "error_description": "Precondition Required"
}

輪詢頻率過高

如果裝置傳送輪詢要求的頻率過高,伺服器會傳回 403 HTTP 回應狀態碼 (Forbidden)。回應包含下列錯誤:

{
  "error": "slow_down",
  "error_description": "Forbidden"
}

其他錯誤

如果輪詢要求缺少任何必要參數或參數值不正確,授權伺服器也會傳回錯誤。這些要求通常包含 400 (Bad Request) 或 401 (Unauthorized) HTTP 回應狀態碼。這類錯誤包括:

發生錯誤 HTTP 狀態碼 說明
admin_policy_enforced 400 Google 帳戶無法授權一或多個要求的範圍,因此無法授權給這些 Google Workspace 管理員的政策。請參閱 Google Workspace 管理員說明文章「控管哪些第三方應用程式和內部應用程式可存取 Google Workspace 資料」,進一步瞭解管理員如何限制範圍的存取權,直到 OAuth 用戶端 ID 明確授予存取權為止。
invalid_client 401

找不到 OAuth 用戶端。舉例來說,如果 client_id 參數值無效,就會發生這個錯誤。

OAuth 用戶端類型不正確。確認用戶端 ID 的應用程式類型已設為「電視和受限制的輸入裝置」

invalid_grant 400 code 參數值無效、已聲明擁有權或無法剖析。
unsupported_grant_type 400 grant_type 參數值無效。
org_internal 403 要求中的 OAuth 用戶端 ID 屬於某項專案,可限制特定 Google Cloud 機構對 Google 帳戶的存取權限。確認 OAuth 應用程式的使用者類型設定

呼叫 Google API

應用程式取得存取權杖後,在獲得 API 所需的存取權範圍後,您即可使用權杖,代表指定使用者帳戶呼叫 Google API。如要這麼做,請在對 API 的要求中加入存取權杖,方法是加入 access_token 查詢參數或 Authorization HTTP 標頭 Bearer 值。如果可以的話,建議使用 HTTP 標頭,因為查詢字串通常會顯示在伺服器記錄檔中。在大部分的情況下,您都可以使用用戶端程式庫,設定對 Google API 的呼叫 (例如呼叫 YouTube Data API 時)。

請注意,YouTube Data API 僅支援擁有及管理多個 YouTube 頻道的 YouTube 內容擁有者 (例如唱片公司和電影公司) 的服務帳戶。

如要試用所有 Google API 及查看其範圍,請前往 OAuth 2.0 Playground

HTTP GET 範例

使用 Authorization: Bearer HTTP 標頭呼叫 youtube.channels 端點 (YouTube Data API) 的呼叫可能如下所示。請注意,您必須指定自己的存取權杖:

GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

以下示範如何使用 access_token 查詢字串參數,為通過驗證的使用者呼叫相同的 API:

GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

curl 個樣本

您可以使用 curl 指令列應用程式測試這些指令。以下為使用 HTTP 標頭選項的範例 (建議):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true

或者,您也可以使用查詢字串參數選項:

curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

重新整理存取權杖

存取權杖會定期過期,並成為相關 API 要求的無效憑證。如果您要求存取與權杖相關聯的範圍,則可以重新整理存取權杖,而無須提示使用者授予權限 (包括沒有使用者時)。

為了重新整理存取權杖,應用程式會將 HTTPS POST 要求傳送至 Google 的授權伺服器 (https://oauth2.googleapis.com/token),其中包含下列參數:

欄位
client_id API Console取得的用戶端 ID。
client_secret API Console取得的用戶端密鑰。
grant_type OAuth 2.0 規格所定義,這個欄位的值必須設為 refresh_token
refresh_token 授權碼交換時傳回的更新權杖。

下列程式碼片段為要求範例:

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

client_id=your_client_id&
client_secret=your_client_secret&
refresh_token=refresh_token&
grant_type=refresh_token

只要使用者尚未撤銷授予應用程式的存取權,憑證伺服器就會傳回內含新存取權杖的 JSON 物件。以下程式碼片段為回應範例:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
  "token_type": "Bearer"
}

請注意,系統即將核發的更新權杖數量有限制;每個用戶端/使用者組合各有一項限制,所有用戶端對每位使用者另有限制。建議您將更新權杖儲存在長期儲存空間,只要該權杖維持有效狀態,就能繼續使用。如果您的應用程式要求過多的更新權杖,可能會達到這些限制,而較舊的更新權杖就會停止運作。

撤銷權杖

在某些情況下,使用者可能會希望撤銷應用程式的存取權。使用者可以透過 帳戶設定撤銷存取權。詳情請參閱「針對具有您帳戶存取權的第三方網站和應用程式,移除網站或應用程式存取權」支援說明文件。

應用程式也可能會透過程式撤銷授予的存取權。在使用者取消訂閱、移除應用程式或應用程式所需的 API 資源發生大幅變更的情況下,程式輔助撤銷程序非常重要。也就是說,移除程序的一部分可以包含 API 要求,確保先前授予應用程式的權限已移除。

如要透過程式輔助方式撤銷權杖,應用程式會向 https://oauth2.googleapis.com/revoke 發出要求,並在參數中加入權杖:

curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
        https://oauth2.googleapis.com/revoke?token={token}

可以是存取權杖或更新權杖。如果權杖是存取權杖,且有對應的更新權杖,系統也會撤銷更新權杖。

如果撤銷成功處理,回應的 HTTP 狀態碼會是 200。如果是錯誤狀況,會傳回 HTTP 狀態碼 400 和錯誤代碼。

允許的範圍

裝置的 OAuth 2.0 流程僅支援下列範圍:

OpenID ConnectGoogle 登入

  • email
  • openid
  • profile

Drive API

  • https://www.googleapis.com/auth/drive.appdata
  • https://www.googleapis.com/auth/drive.file

YouTube API

  • https://www.googleapis.com/auth/youtube
  • https://www.googleapis.com/auth/youtube.readonly