針對用戶端網頁應用程式使用 OAuth 2.0

本文說明如何實作 OAuth 2.0 授權,從 JavaScript 網頁應用程式存取 YouTube Data API。OAuth 2.0 可讓使用者與應用程式共用特定資料,同時保有使用者名稱、密碼和其他資訊的隱私。舉例來說,應用程式可以使用 OAuth 2.0 取得頻道 YouTube 資料擷取權限。

這個 OAuth 2.0 流程稱為「隱含授權流程」。限制僅在使用者於應用程式使用時存取 API。這些應用程式無法儲存機密資訊。

在這個流程中,您的應用程式會開啟 Google 網址,使用查詢參數來識別應用程式,以及應用程式所需的 API 存取權類型。您可以在目前的瀏覽器視窗或彈出式視窗中開啟網址。使用者可以透過 Google 進行驗證,並授予要求的權限。接著,Google 會將使用者重新導向回您的應用程式。重新導向程序包含存取權杖,可供應用程式驗證並用於提出 API 要求。

Google API 用戶端程式庫和 Google Identity 服務

如果您使用 JavaScript 專用的 Google API 用戶端程式庫執行授權呼叫,應使用 Google Identity 服務 JavaScript 程式庫來處理 OAuth 2.0 流程。請參閱 Google Identity Services 的權杖模型,這種模型是以 OAuth 2.0 隱含授權流程為基礎。

先備知識

為專案啟用 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. 填妥表單。如果應用程式使用 JavaScript 發出已授權的 Google API 要求,就必須指定已授權的 JavaScript 來源。來源識別應用程式可以從哪些網域傳送要求至 OAuth 2.0 伺服器。這些來源必須遵守 Google 的驗證規則

識別存取權範圍

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

開始實作 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 API 範圍文件完整列出了可用於存取 Google API 的範圍。

取得 OAuth 2.0 存取權杖

下列步驟說明應用程式如何與 Google OAuth 2.0 伺服器互動,取得使用者的同意並代表使用者執行 API 要求。您的應用程式必須先取得同意,才能執行需要使用者授權的 Google API 要求。

步驟 1:重新導向至 Google 的 OAuth 2.0 伺服器

如需要求存取使用者資料的權限,請將使用者重新導向至 Google 的 OAuth 2.0 伺服器。

OAuth 2.0 端點

產生網址,透過位於 https://accounts.google.com/o/oauth2/v2/auth 的 Google OAuth 2.0 端點要求存取權。這個端點可透過 HTTPS 存取,因此系統拒絕使用一般 HTTP 連線。

Google 授權伺服器針對網路伺服器應用程式支援下列查詢字串參數:

參數
client_id 必要

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

redirect_uri 必要

決定使用者完成授權流程後,API 伺服器將使用者重新導向的目的地。這個值必須與您在用戶端 API Console Credentials page中設定的 OAuth 2.0 用戶端授權重新導向 URI 完全相符。如果這個值與所提供 client_id 的授權重新導向 URI 不符,您會收到 redirect_uri_mismatch 錯誤。

請注意,httphttps 配置、大小寫和結尾的斜線 (「/」) 必須全部相符。

response_type 必要

JavaScript 應用程式必須將參數值設為 token。這個值會指示 Google 授權伺服器在 URI (#) 的片段 ID (#) 中傳回存取權杖做為 name=value 組合,系統會在完成授權程序後將使用者重新導向至該組。

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。

建議您讓應用程式盡可能在情境中要求授權範圍的存取權。透過漸進式授權在情境下要求存取使用者資料,可讓使用者輕鬆瞭解應用程式需要要求存取權的原因。

state 建議採用

指定應用程式用來維持授權要求與授權伺服器回應之間狀態的任何字串值。使用者同意或拒絕應用程式的存取要求後,伺服器會透過 redirect_uri 的網址片段 ID (#) 傳回您以 name=value 組合形式傳送的確切值。

您可以將這個參數用於多種用途,例如將使用者導向至應用程式中的正確資源、傳送 Nonce,以及降低跨網站要求的偽造情形。由於 redirect_uri 可以猜測,因此使用 state 值可讓您保證傳入連線是因驗證要求而產生的結果。如果您產生隨機字串或對 Cookie 雜湊或其他擷取用戶端狀態的值進行編碼,則您可以驗證回應,另外確保要求和回應源自相同的瀏覽器,提供防範跨網站要求偽造這類攻擊的防護措施。如需如何建立並確認 state 權杖的範例,請參閱 OpenID Connect 說明文件。

include_granted_scopes 選用

可讓應用程式使用漸進式授權,要求在相關情境下存取其他範圍。如果將這個參數的值設為 true,且已授予授權要求,則新的存取權杖也會涵蓋使用者先前授予應用程式存取權的所有範圍。如需示例,請參閱漸進式授權一節。

login_hint 選用

如果應用程式知道想要驗證的使用者,可使用此參數來提示 Google 驗證伺服器。伺服器會在登入表單中預先填入電子郵件欄位,或選取適當的多登入工作階段,並根據提示簡化登入流程。

將參數值設為電子郵件地址或 sub ID,這相當於使用者的 Google ID。

prompt 選用

以空格分隔且區分大小寫的提示清單,用於向使用者顯示。如未指定這個參數,系統只會在專案第一次要求存取權時提示使用者。詳情請參閱「 提示重新取得同意聲明」。

可能的值為:

none 不要顯示任何驗證或同意畫面。請勿使用其他值指定。
consent 提示使用者表示同意。
select_account 提示使用者選取帳戶。

重新導向至 Google 授權伺服器的範例

以下範例網址顯示了換行符號及方便閱讀的空格。該網址會要求存取範圍,以便擷取使用者的 YouTube 資料。這項服務使用漸進式授權 (include_granted_scopes=true),確保新的存取權杖涵蓋使用者先前授予應用程式存取權的任何範圍。本範例中也設定了其他幾個參數。

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 client_id=client_id

建立要求網址之後,請將使用者重新導向至該網址。

JavaScript 程式碼範例

下列 JavaScript 程式碼片段說明如何在不使用 JavaScript 適用的 Google API 用戶端程式庫的情況下,以 JavaScript 啟動授權流程。由於這個 OAuth 2.0 端點不支援跨來源資源共用 (CORS),因此程式碼片段會建立表單來開啟對該端點的要求。

/*
 * Create form to request access token from Google's OAuth 2.0 server.
 */
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

  // Create <form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);

  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client_id': 'YOUR_CLIENT_ID',
                'redirect_uri': 'YOUR_REDIRECT_URI',
                'response_type': 'token',
                'scope': 'https://www.googleapis.com/auth/youtube.force-ssl',
                'include_granted_scopes': 'true',
                'state': 'pass-through value'};

  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

步驟 2:Google 會提示使用者同意

在這個步驟中,使用者決定是否授予應用程式要求的存取權。在這個階段,Google 會顯示同意視窗,其中顯示您的應用程式名稱,以及本身透過使用者的授權憑證要求取得權限的 Google API 服務,並大致說明要授予的存取權範圍。然後,使用者就可以同意授予應用程式要求一或多個範圍的存取權,或是拒絕要求。

應用程式會等待來自 Google OAuth 2.0 伺服器的回應,並指出是否已獲得任何存取權,因此在這個階段無須採取任何行動。該回應會在下列步驟中說明。

錯誤

向 Google 的 OAuth 2.0 授權端點發出的要求可能會顯示要向使用者顯示的錯誤訊息,而非預期的驗證和授權流程。以下列出常見的錯誤代碼和建議解決方法。

admin_policy_enforced

Google 帳戶無法授權一或多個要求的範圍,因此無法授權給這個 Google Workspace 管理員的政策。請參閱 Google Workspace 管理員說明文章「 控管哪些第三方應用程式和內部應用程式可存取 Google Workspace 資料」一文,進一步瞭解系統管理員如何限制所有範圍,或是敏感和受限制範圍的存取權,直到 OAuth 用戶端 ID 明確授予存取權為止。

disallowed_useragent

授權端點會顯示在 Google 的 OAuth 2.0 政策禁止的內嵌使用者代理程式中。

Android

android.webkit.WebView 中開啟授權要求時,Android 開發人員可能會看到這則錯誤訊息。開發人員應改用 Android 程式庫,例如 Android 專用 Google 登入或 OpenID Foundation 的 Android 適用的 AppAuth

當 Android 應用程式透過內嵌的使用者代理程式開啟一般網頁連結,且使用者從您的網站前往 Google 的 OAuth 2.0 授權端點時,網頁開發人員可能就會發生這個錯誤。開發人員應允許在作業系統的預設連結處理常式 (包括 Android 應用程式連結處理常式或預設的瀏覽器應用程式) 中開啟一般連結。您也可以使用 Android 自訂分頁程式庫。

iOS

iOS 和 macOS 開發人員在 WKWebView 中開啟授權要求時,可能會發生這個錯誤。開發人員應改用 iOS 程式庫,例如 iOS 專用 Google 登入或 OpenID Foundation 的 AppAuth for iOS

當 iOS 或 macOS 應用程式透過內嵌的使用者代理程式開啟一般網路連結,且使用者從您的網站前往 Google 的 OAuth 2.0 授權端點時,網頁開發人員可能就會發生這個錯誤。開發人員應允許在作業系統的預設連結處理常式中開啟一般連結,包括通用連結處理常式或預設的瀏覽器應用程式。您也可以使用 SFSafariViewController 程式庫。

org_internal

要求中的 OAuth 用戶端 ID 屬於某項專案,可限制特定 Google Cloud 機構對 Google 帳戶的存取權限。如要進一步瞭解這項設定選項,請參閱「設定 OAuth 同意畫面」說明文章中的「使用者類型」一節。

invalid_client

提出要求的來源並未獲得該用戶端的授權。詳情請參閱 origin_mismatch

invalid_grant

使用漸進式授權時,權杖可能已過期或失效。再次驗證使用者,並要求使用者同意取得新的權杖。如果持續看到這個錯誤,請確認應用程式設定正確無誤,且在要求中使用正確的權杖和參數。否則,該使用者帳戶可能已遭刪除或停用。

origin_mismatch

授權要求的來源 JavaScript 配置、網域和/或通訊埠,可能不符合為 OAuth 用戶端 ID 註冊的已授權 JavaScript 來源 URI。查看 Google API Console Credentials page中已授權的 JavaScript 來源。

redirect_uri_mismatch

授權要求中傳遞的 redirect_uri 與 OAuth 用戶端 ID 的授權重新導向 URI 不符。查看 Google API Console Credentials page中已授權的重新導向 URI。

授權要求的來源 JavaScript 配置、網域和/或通訊埠,可能不符合為 OAuth 用戶端 ID 註冊的已授權 JavaScript 來源 URI。查看 Google API Console Credentials page中已授權的 JavaScript 來源。

redirect_uri 參數可能是指 OAuth 外架構 (OOB) 流程,但該流程已淘汰且不再受支援。如要更新整合作業,請參閱遷移指南

invalid_request

您提出的要求發生問題。可能原因如下:

  • 要求的格式不正確
  • 要求中缺少必要參數
  • 這項要求使用了 Google 不支援的授權方法。確認 OAuth 整合功能使用建議的整合方法

步驟 3:處理 OAuth 2.0 伺服器回應

OAuth 2.0 端點

OAuth 2.0 伺服器會將回應傳送至您在存取權杖要求中指定的 redirect_uri

如果使用者核准要求,回應就會提供存取權杖。如果使用者未核准要求,回應會包含錯誤訊息。存取權杖或錯誤訊息會在重新導向 URI 的雜湊片段上傳回,如下所示:

  • 存取權杖回應:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

    除了 access_token 參數以外,片段字串也包含一律設為 Bearertoken_type 參數,以及指定權杖生命週期的 expires_in 參數 (以秒為單位)。如果在存取權杖要求中指定 state 參數,參數的值也會包含在回應中。

  • 錯誤回應:
    https://oauth2.example.com/callback#error=access_denied

OAuth 2.0 伺服器回應範例

如要測試這個流程,請點選下列範例網址,該網址會要求查看 Google 雲端硬碟中檔案中繼資料的唯讀存取權:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 client_id=client_id

完成 OAuth 2.0 流程後,系統會將您重新導向至 http://localhost/oauth2callback。除非本機電腦發生在該網址提供檔案,否則該網址會產生 404 NOT FOUND 錯誤。當使用者被重新導向返回應用程式時,下一個步驟將提供 URI 中傳回資訊的詳細資訊。

呼叫 Google API

OAuth 2.0 端點

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

請注意,YouTube Live Streaming API 不支援服務帳戶流程。由於無法將服務帳戶連結至 YouTube 帳戶,因此嘗試透過此流程授權要求時,會產生 NoLinkedYouTubeAccount 錯誤。

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

HTTP GET 範例

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

GET /youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

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

GET https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true

curl 個樣本

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

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true

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

curl https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true

JavaScript 程式碼範例

下列程式碼片段示範如何使用 CORS (跨源資源共享) 將要求傳送至 Google API。本例未使用 JavaScript 的 Google API 用戶端程式庫,不過,即使您並未使用用戶端程式庫,該程式庫說明文件中的 CORS 支援指南也許能協助您進一步瞭解這些要求。

在這個程式碼片段中,access_token 變數代表您取得的權杖,用來代表授權使用者提出 API 要求。完整範例示範如何將權杖儲存至瀏覽器的本機儲存空間,並在提出 API 要求時擷取該權杖。

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id,snippet&mine=true' +
    'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
  console.log(xhr.response);
};
xhr.send(null);

完整範例

OAuth 2.0 端點

這個程式碼範例示範如何在不使用 JavaScript 的 Google API 用戶端程式庫的情況下,以 JavaScript 完成 OAuth 2.0 流程。這段程式碼適用於顯示按鈕試用 API 要求的 HTML 網頁。如果您按一下該按鈕,程式碼會檢查網頁是否已在瀏覽器的本機儲存空間中儲存 API 存取權杖。如果相符,就會執行 API 要求。否則會啟動 OAuth 2.0 流程。

如果是 OAuth 2.0 流程,頁面會顯示下列步驟:

  1. 系統會將使用者導向至 Google 的 OAuth 2.0 伺服器,該伺服器會要求存取 https://www.googleapis.com/auth/youtube.force-ssl 範圍。
  2. 授予 (或拒絕) 對一或多個要求範圍的存取權後,系統會將使用者重新導向至原始網頁,以便剖析片段 ID 字串中的存取權杖。
  3. 這個網頁會使用存取權杖發出範例 API 要求。

    這個 API 要求會呼叫 YouTube Data API 的 liveBroadcasts.list 方法,擷取授權使用者 YouTube 頻道的影片廣播清單。

  4. 如果要求成功執行,API 回應就會記錄在瀏覽器的偵錯控制台中。

您可以透過 Google 帳戶的權限頁面撤銷應用程式的存取權。系統會將該應用程式列為 Google API 文件的 OAuth 2.0 示範版本

如要在本機執行此程式碼,您需要設定與授權憑證對應的 YOUR_CLIENT_IDYOUR_REDIRECT_URI 變數值。YOUR_REDIRECT_URI 變數應設為提供網頁的相同網址。這個值必須與您在 API Console Credentials page中設定的 OAuth 2.0 用戶端授權重新導向 URI 完全相符。如果這個值與授權的 URI 不符,您會收到 redirect_uri_mismatch 錯誤。您的專案也必須針對這項要求啟用適當的 API

<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var fragmentString = location.hash.substring(1);
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0 && params['state']) {
    if (params['state'] == localStorage.getItem('state')) {
      localStorage.setItem('oauth2-test-params', JSON.stringify(params) );

      trySampleRequest();
    } else {
      console.log('State mismatch. Possible CSRF attack');
    }
  }

  // Function to generate a random state value
  function generateCryptoRandomState() {
    const randomValues = new Uint32Array(2);
    window.crypto.getRandomValues(randomValues);

    // Encode as UTF-8
    const utf8Encoder = new TextEncoder();
    const utf8Array = utf8Encoder.encode(
      String.fromCharCode.apply(null, randomValues)
    );

    // Base64 encode the UTF-8 data
    return btoa(String.fromCharCode.apply(null, utf8Array))
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=+$/, '');
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id,snippet&mine=true' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*
   * Create form to request access token from Google's OAuth 2.0 server.
   */
  function oauth2SignIn() {
    // create random state value and store in local storage
    var state = generateCryptoRandomState();
    localStorage.setItem('state', state);

    // Google's OAuth 2.0 endpoint for requesting an access token
    var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/youtube.force-ssl',
                  'state': state,
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

JavaScript 來源驗證規則

Google 會將下列驗證規則套用至 JavaScript 來源,協助開發人員保護應用程式的安全。您的 JavaScript 來源必須遵循這些規則。如要瞭解網域、主機和配置的定義,請參閱 RFC 3986 第 3 節

驗證規則
配置

JavaScript 來源必須使用 HTTPS 通訊協定,而非純文字 HTTP。本機主機 URI (包括 localhost IP 位址 URI) 不在這項規則的涵蓋範圍內。

主機

主機不得為原始 IP 位址。本機主機 IP 位址不在這項規則範圍內。

網域
  • 主機 TLD (頂層網域) 必須列在公開尾碼清單中。
  • 主機網域不得為 “googleusercontent.com”
  • 除非應用程式擁有網址,否則 JavaScript 來源不能包含網址縮短網域 (例如 goo.gl)。
  • 使用者資訊

    JavaScript 來源不可包含 userinfo 子元件。

    路徑

    JavaScript 來源不能包含路徑元件。

    查詢

    JavaScript 來源不能包含查詢元件。

    Fragment

    JavaScript 來源不能包含片段元件。

    字元 JavaScript 來源不得包含特定字元,包括:
    • 萬用字元字元 ('*')
    • 不可列印的 ASCII 字元
    • 百分比編碼無效 (任何百分比編碼未遵循網址編碼形式的百分比符號後接兩個十六進位數字)
    • 空值字元 (編碼的 NULL 字元,例如%00%C0%80)

    漸進式授權

    在 OAuth 2.0 通訊協定中,您的應用程式要求授權存取資源,這些資源由範圍識別。在您需要的時候,對資源提出授權要求是最佳的使用者體驗。為了啟用這個做法,Google 的授權伺服器支援漸進式授權。這項功能可讓您視需要要求範圍,如果使用者授予新範圍的權限,則會傳回授權碼。當使用者授予專案的所有範圍,這個權杖就會傳回授權碼。

    舉例來說,假設應用程式會擷取已驗證使用者的 YouTube 頻道資料,並且允許使用者透過特殊流程擷取 YouTube Analytics (分析) 資料。在這種情況下,應用程式可能會在登入時要求存取 https://www.googleapis.com/auth/youtube.force-ssl 範圍。不過,如果使用者嘗試存取自己頻道的 Analytics (分析) 資料,應用程式也可以要求存取 https://www.googleapis.com/auth/yt-analytics.readonly 範圍。

    下列規則適用於從漸進式授權取得的存取權杖:

    • 權杖可用於存取與納入新合併授權的任一範圍相對應的資源。
    • 當您使用更新權杖取得合併授權以取得存取權杖時,存取權杖代表合併的授權,可以用於回應中包含的任何 scope 值。
    • 合併授權包括使用者授予 API 專案的所有範圍,即使授權是透過不同用戶端要求也是如此。舉例來說,如果使用者利用應用程式的桌面用戶端授予一個範圍的存取權,然後透過行動用戶端將另一個範圍授予同一應用程式,則合併授權會包括這兩個範圍。
    • 如果撤銷代表合併授權的權杖,系統會同時撤銷代表相關聯使用者的所有授權範圍存取權。

    下列程式碼範例說明如何將範圍新增至現有的存取權杖。這樣一來,您的應用程式就不必管理多個存取權杖。

    OAuth 2.0 端點

    在本範例中,除了使用者已授予應用程式的任何其他存取權,發出呼叫的應用程式也會要求擷取使用者的 YouTube 資料,以擷取使用者的 YouTube 資料。

    如要將範圍新增至現有的存取權杖,請在對 Google OAuth 2.0 伺服器發出的要求中加入 include_granted_scopes 參數。

    下列程式碼片段說明如何執行這項作業。程式碼片段假設您已將存取權杖有效的範圍儲存在瀏覽器本機儲存空間中。(完整範例程式碼會儲存瀏覽器本機儲存空間中的 oauth2-test-params.scope 屬性,藉此儲存存取權杖有效的範圍清單)。

    程式碼片段會比較存取權杖的有效範圍,並針對特定查詢使用的範圍。如果存取權杖未涵蓋該範圍,OAuth 2.0 流程就會啟動。這裡的 oauth2SignIn 函式與步驟 2 中的函式相同 (將於稍後的完整範例中提供)。

    var SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    撤銷權杖

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

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

    OAuth 2.0 端點

    如要透過程式輔助方式撤銷權杖,應用程式會向 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 和錯誤代碼。

    下列 JavaScript 程式碼片段說明如何在不使用 JavaScript 適用的 Google API 用戶端程式庫的情況下,以 JavaScript 撤銷權杖。由於用於撤銷權杖的 Google OAuth 2.0 端點不支援跨源資源共享 (CORS),因此程式碼會建立表單並提交表單至端點,而不是使用 XMLHttpRequest() 方法發布要求。

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }