本文說明如何導入 OAuth 2.0 授權,從 JavaScript 網頁應用程式存取 Google API。OAuth 2.0 可讓使用者與應用程式共用特定資料,同時保有使用者名稱、密碼和其他資訊的隱私。舉例來說,應用程式可以使用 OAuth 2.0 取得使用者授權,將檔案儲存在他們的 Google 雲端硬碟中。
這個 OAuth 2.0 流程稱為「隱含授權流程」。這項功能適用於僅在使用者位於應用程式時存取 API 的應用程式。這些應用程式無法儲存機密資訊。
在這個流程中,應用程式會開啟 Google 網址,並使用查詢參數來識別應用程式,以及應用程式所需 API 存取權的類型。您可以在目前的瀏覽器視窗或彈出式視窗中開啟網址。使用者可以透過 Google 驗證身分,並授予要求的權限。 接著,Google 會將使用者重新導向回您的應用程式。重新導向會包含存取權杖,您的應用程式會驗證該權杖,然後用來發出 API 要求。
Google API 用戶端程式庫和 Google 身分識別服務
如果您使用 JavaScript 適用的 Google API 用戶端程式庫,向 Google 發出授權呼叫,則應使用 Google Identity Services JavaScript 程式庫處理 OAuth 2.0 流程。請參閱 Google 身分識別服務的權杖模型,該模型是以 OAuth 2.0 隱含授權流程為基礎。
必要條件
為專案啟用 API
呼叫 Google API 的應用程式必須在 API Console中啟用這些 API。
如要為專案啟用 API,請按照下列步驟操作:
- Open the API Library 。 Google API Console
- If prompted, select a project, or create a new one.
- API Library 會列出所有可用的 API,並按照產品系列和熱門程度分組。如果清單裡找不到您想啟用的 API,請使用搜尋功能,或點選所屬產品系列的「查看全部」。
- 選取要啟用的 API,然後按一下「Enable」按鈕。
- If prompted, enable billing.
- If prompted, read and accept the API's Terms of Service.
建立授權憑證
凡是使用 OAuth 2.0 存取 Google API 的應用程式,都必須具備授權憑證,向 Google 的 OAuth 2.0 伺服器識別應用程式。下列步驟說明如何為專案建立憑證。應用程式隨後就能使用這些憑證,存取您為該專案啟用的 API。
- Go to the Credentials page.
- 按一下「建立用戶端」。
- 選取「網頁應用程式」應用程式類型。
- 填妥表單。應用程式必須指定已授權的 JavaScript 來源,才能使用 JavaScript 發出已授權的 Google API 要求。來源會識別應用程式可向 OAuth 2.0 伺服器傳送要求的網域。這些來源必須遵守 Google 的驗證規則。
找出存取權範圍
範圍可讓應用程式僅要求存取其需要的資源,也能讓使用者控制對應用程式授予的存取量。因此,要求範圍的數量與取得使用者同意聲明的可能性之間,可能存在反向關係。
開始實作 OAuth 2.0 授權之前,建議您找出應用程式需要權限存取的範圍。
「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。您可以在 中找到這個值。 |
||||||
redirect_uri |
必要
決定 API 伺服器在使用者完成授權流程後,將使用者重新導向至何處。這個值必須與 OAuth 2.0 用戶端的其中一個授權重新導向 URI 完全相符,您可以在用戶端的
中設定。如果這個值與所提供 請注意, |
||||||
response_type |
必要
JavaScript 應用程式必須將參數值設為 |
||||||
scope |
必要
以空格分隔的範圍清單,用於識別應用程式可代表使用者存取的資源。這些值會提供資訊給 Google,決定要向使用者顯示的同意畫面。 範圍可讓應用程式僅要求存取其需要的資源,也能讓使用者控制對應用程式授予的存取量。因此,要求範圍的數量與取得使用者同意授權的可能性成反比。 建議應用程式盡可能在情境中要求授權範圍的存取權。透過漸進式授權,在相關情境中要求存取使用者資料,有助於使用者瞭解應用程式需要所要求存取權的原因。 |
||||||
state |
建議
指定應用程式用來維護授權要求與授權伺服器回應之間狀態的任何字串值。使用者同意或拒絕應用程式的存取要求後,伺服器會傳回您在 這個參數有多種用途,例如將使用者導向應用程式中的正確資源、傳送隨機數,以及防範跨網站要求偽造。由於 |
||||||
include_granted_scopes |
選填
允許應用程式使用漸進式授權,在相關情境中要求存取其他範圍。如果將這個參數的值設為 |
||||||
enable_granular_consent |
選填
預設為 Google 為應用程式啟用精細權限後,這個參數就不會再有任何作用。 |
||||||
login_hint |
選填
如果應用程式知道要驗證的使用者是誰,就可以使用這個參數向 Google 驗證伺服器提供提示。伺服器會使用提示簡化登入流程,方法是在登入表單中預先填入電子郵件欄位,或是選取適當的多重登入工作階段。 將參數值設為電子郵件地址或 |
||||||
prompt |
選填
以半形空格分隔的提示清單 (區分大小寫),會向使用者顯示。如未指定這個參數,系統只會在專案首次要求存取權時提示使用者。詳情請參閱 提示重新取得同意聲明。 可能的值為:
|
重新導向至 Google 授權伺服器的範例
以下是網址範例,為方便閱讀,已加入換行符和空格。
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& include_granted_scopes=true& response_type=token& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/code& client_id=client_id
建立要求網址後,請將使用者重新導向至該網址。
JavaScript 程式碼範例
下列 JavaScript 程式碼片段顯示如何在 JavaScript 中啟動授權流程,而不使用 JavaScript 適用的 Google API 用戶端程式庫。由於這個 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/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly', '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 Workspace 管理員的政策,Google 帳戶無法授權一或多個要求範圍。如要進一步瞭解管理員如何限制所有範圍或機密和受限範圍的存取權,直到明確授予 OAuth 用戶端 ID 存取權為止,請參閱 Google Workspace 管理員說明文章「 控管哪些第三方應用程式和內部應用程式可存取 Google Workspace 資料」。
disallowed_useragent
授權端點顯示在 Google 的 OAuth 2.0 政策禁止使用的內嵌使用者代理程式中。
Android
Android 開發人員在 android.webkit.WebView
中開啟授權要求時,可能會看到這則錯誤訊息。開發人員應改用 Android 程式庫,例如 Google Sign-In for Android 或 OpenID Foundation 的 AppAuth for Android。
如果 Android 應用程式在內嵌使用者代理程式中開啟一般網頁連結,且使用者從您的網站前往 Google 的 OAuth 2.0 授權端點,網頁開發人員可能會遇到這個錯誤。開發人員應允許一般連結在作業系統的預設連結處理常式中開啟,包括 Android 應用程式連結處理常式或預設瀏覽器應用程式。Android 自訂分頁程式庫也是支援的選項。
iOS
iOS 和 macOS 開發人員在 WKWebView
中開啟授權要求時,可能會遇到這項錯誤。開發人員應改用 iOS 程式庫,例如 Google Sign-In for iOS 或 OpenID Foundation 的 AppAuth for iOS。
如果 iOS 或 macOS 應用程式在內嵌的使用者代理程式中開啟一般網頁連結,且使用者從您的網站前往 Google 的 OAuth 2.0 授權端點,網頁開發人員可能會遇到這個錯誤。開發人員應允許一般連結在作業系統的預設連結處理常式中開啟,包括通用連結處理常式或預設瀏覽器應用程式。SFSafariViewController
程式庫也是支援的選項。
org_internal
要求中的 OAuth 用戶端 ID 屬於專案,該專案限制只能存取特定 Google Cloud 機構中的 Google 帳戶。如要進一步瞭解這個設定選項,請參閱「設定 OAuth 同意畫面」說明文章中的「使用者類型」一節。
invalid_client
提出要求的來源未獲授權使用這個用戶端。詳情請參閱 origin_mismatch
。
deleted_client
用來提出要求的 OAuth 用戶端已遭刪除。您可以手動刪除,也可以讓系統在未使用的用戶端 中自動刪除。刪除用戶端後,您可以在 30 天內還原。 瞭解詳情 。
invalid_grant
使用增量授權時,權杖可能已過期或失效。 再次驗證使用者身分,並徵求使用者同意,以取得新權杖。如果持續看到這則錯誤訊息,請確認應用程式設定正確無誤,且要求中使用的權杖和參數正確無誤。否則,使用者帳戶可能已遭刪除或停用。
origin_mismatch
發出授權要求的 JavaScript 的通訊協定、網域和/或連接埠,可能與為 OAuth 用戶端 ID 註冊的授權 JavaScript 來源 URI 不符。在 中查看已授權的 JavaScript 來源。
redirect_uri_mismatch
授權要求中傳遞的 redirect_uri
與 OAuth 用戶端 ID 的授權重新導向 URI 不符。在
中,查看已授權的重新導向 URI。
發出授權要求的 JavaScript 的通訊協定、網域和/或連接埠,可能與為 OAuth 用戶端 ID 註冊的授權 JavaScript 來源 URI 不符。在 中,查看已授權的 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
參數外,片段字串也包含token_type
參數 (一律設為Bearer
) 和expires_in
參數 (以秒為單位指定權杖的生命週期)。如果存取權杖要求中指定了state
參數,回應中也會包含該參數的值。- 錯誤回應:
https://oauth2.example.com/callback#error=access_denied
OAuth 2.0 伺服器回應範例
您可以點選下列範例網址測試這個流程,該網址會要求取得唯讀存取權,以便查看 Google 雲端硬碟中的檔案中繼資料,以及查看 Google 日曆活動的唯讀存取權:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& include_granted_scopes=true& response_type=token& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/code& client_id=client_id
完成 OAuth 2.0 流程後,系統會將您重新導向至 http://localhost/oauth2callback
。除非本機電腦剛好在該位址提供檔案,否則該網址會產生 404 NOT FOUND
錯誤。在使用者重新導向回應用程式時,下一個步驟會詳細說明 URI 中傳回的資訊。
步驟 4:檢查使用者授予的範圍
要求多項權限 (範圍) 時,使用者可能不會授予應用程式所有權限。應用程式必須驗證實際授予的範圍,並妥善處理部分權限遭拒的情況,通常是停用依賴這些遭拒範圍的功能。
但也有例外情況。如果 Google Workspace Enterprise 應用程式已啟用網域範圍的授權委派,或是標示為信任,系統就會略過詳細權限同意畫面。這類應用程式不會顯示精細權限同意畫面。應用程式會收到所有要求的範圍,或完全沒有。
詳情請參閱「如何處理精細權限」。
OAuth 2.0 端點
如要檢查使用者是否已授予應用程式特定範圍的存取權,請檢查存取權杖回應中的 scope
欄位。存取權範圍 (以空格分隔的字串清單表示,且區分大小寫)。
舉例來說,下列存取權杖回應範例指出,使用者已授予應用程式唯讀存取雲端硬碟活動和日曆活動的權限:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
呼叫 Google API
OAuth 2.0 端點
應用程式取得存取權杖後,如果 API 要求的存取範圍已獲授權,您就可以使用權杖代表特定使用者帳戶呼叫 Google API。如要這麼做,請在 API 要求中加入存取權杖,方法是加入 access_token
查詢參數或 Authorization
HTTP 標頭 Bearer
值。如果可以,請盡量使用 HTTP 標頭,因為查詢字串通常會顯示在伺服器記錄中。在大多數情況下,您可以使用用戶端程式庫設定對 Google API 的呼叫 (例如呼叫 Drive Files API 時)。
您可以在 OAuth 2.0 Playground 試用所有 Google API,並查看其範圍。
HTTP GET 範例
使用 Authorization: Bearer
HTTP 標頭呼叫
drive.files
端點 (Drive Files API) 時,可能如下所示。請注意,您必須指定自己的存取權杖:
GET /drive/v2/files HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
以下是使用 access_token
查詢字串參數,對經過驗證的使用者呼叫相同 API 的範例:
GET https://www.googleapis.com/drive/v2/files?access_token=access_token
curl
範例
您可以使用 curl
指令列應用程式測試這些指令。以下是使用 HTTP 標頭選項的範例 (建議採用):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files
或者,您也可以使用查詢字串參數選項:
curl https://www.googleapis.com/drive/v2/files?access_token=access_token
JavaScript 程式碼範例
下列程式碼片段示範如何使用 CORS (跨來源資源共享) 將要求傳送至 Google API。本範例未使用 Google API JavaScript 專用用戶端程式庫。 不過,即使您未使用用戶端程式庫,該程式庫說明文件中的 CORS 支援指南,可能也有助於您進一步瞭解這些要求。
在這個程式碼片段中,access_token
變數代表您取得的權杖,可代表授權使用者發出 API 要求。完整範例會示範如何將該權杖儲存在瀏覽器的本機儲存空間,並在發出 API 要求時擷取權杖。
var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.googleapis.com/drive/v3/about?fields=user&' + 'access_token=' + params['access_token']); xhr.onreadystatechange = function (e) { console.log(xhr.response); }; xhr.send(null);
完整範例
OAuth 2.0 端點
這個程式碼範例示範如何在 JavaScript 中完成 OAuth 2.0 流程,而不使用 Google API JavaScript 專用用戶端程式庫。這段程式碼適用於 HTML 網頁,會顯示一個按鈕,讓您試用 API 要求。如果您點選按鈕,程式碼會檢查網頁是否已在瀏覽器的本機儲存空間中儲存 API 存取權杖。如果是,就會執行 API 要求。否則,系統會啟動 OAuth 2.0 流程。
對於 OAuth 2.0 流程,網頁會執行下列步驟:
- 將使用者導向 Google 的 OAuth 2.0 伺服器,要求存取
https://www.googleapis.com/auth/drive.metadata.readonly
和https://www.googleapis.com/auth/calendar.readonly
範圍。 - 授權 (或拒絕) 存取一或多個要求的範圍後,使用者會重新導向至原始網頁,該網頁會剖析片段 ID 字串中的存取權杖。
- 這個頁面會檢查使用者已授予應用程式哪些範圍的存取權。
如果使用者已授予所要求範圍的存取權,網頁會使用存取權杖發出範例 API 要求。
API 要求會呼叫 Google Drive API 的
about.get
方法,擷取授權使用者 Google 雲端硬碟帳戶的相關資訊。- 如果要求順利執行,API 回應會記錄在瀏覽器的偵錯控制台中。
如要撤銷應用程式的存取權,請前往 Google 帳戶的「權限」頁面。應用程式會列為「OAuth 2.0 Demo for Google API Docs」。
如要在本機執行這段程式碼,您需要為 YOUR_CLIENT_ID
和 YOUR_REDIRECT_URI
變數設定對應授權憑證的值。YOUR_REDIRECT_URI
變數應設為提供網頁的網址。這個值必須與 OAuth 2.0 用戶端的其中一個授權重新導向 URI 完全相符,您可以在
中設定這些 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']) { // User authorized the request. Now, check which scopes were granted. if (params['scope'].includes('https://www.googleapis.com/auth/drive.metadata.readonly')) { // User authorized read-only Drive activity permission. // Calling the APIs, etc. var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.googleapis.com/drive/v3/about?fields=user&' + '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 { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly console.log('User did not authorize read-only Drive activity permission.'); } // Check if user authorized Calendar read permission. if (params['scope'].includes('https://www.googleapis.com/auth/calendar.readonly')) { // User authorized Calendar read permission. // Calling the APIs, etc. console.log('User authorized Calendar read permission.'); } else { // User didn't authorize Calendar read permission. // Update UX and application accordingly console.log('User did not authorize Calendar read permission.'); } } 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/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly', '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 (包括本機主機 IP 位址 URI) 不受這項規則限制。 |
主機 |
主機不得為原始 IP 位址。本機主機 IP 位址不受這項規則限制。 |
網域 |
“googleusercontent.com” 。goo.gl ),除非應用程式擁有該網域。 |
Userinfo |
JavaScript 來源不得包含使用者資訊子元件。 |
路徑 |
JavaScript 來源不得包含路徑元件。 |
查詢 |
JavaScript 來源不得包含查詢元件。 |
Fragment |
JavaScript 來源不得包含片段元件。 |
字元數 |
JavaScript 來源不得包含特定字元,包括:
|
增量授權
在 OAuth 2.0 通訊協定中,應用程式會要求授權存取資源,這些資源由範圍識別。在需要資源時要求授權,是提供最佳使用者體驗的做法。為啟用這項做法,Google 的授權伺服器支援增量授權。這項功能可讓您視需要要求範圍,如果使用者授予新範圍的權限,系統會傳回授權碼,該授權碼可換取權杖,其中包含使用者授予專案的所有範圍。
舉例來說,如果應用程式可讓使用者試聽音樂曲目及製作混音,可能只需要極少的資源 (或許只有登入者的名稱),不過,如要儲存完成的組合,必須存取對方的 Google 雲端硬碟。如果應用程式只在實際需要時要求存取 Google 雲端硬碟,大多數使用者都會覺得很自然。
在這個案例中,應用程式可能會在登入時要求 openid
和 profile
範圍,執行基本登入作業,然後在首次要求儲存混音時,要求 https://www.googleapis.com/auth/drive.file
範圍。
透過增量授權取得的存取權杖適用下列規則:
- 您可以使用這個權杖,存取與新合併授權中任何範圍對應的資源。
- 使用複合授權的重新整理權杖取得存取權杖時,存取權杖代表複合授權,可用於回應中包含的任何
scope
值。 - 即使授權是從不同用戶端要求,合併授權仍會包含使用者授予 API 專案的所有範圍。舉例來說,如果使用者透過應用程式的電腦版用戶端授予某個範圍的存取權,然後透過行動版用戶端授予相同應用程式另一個範圍的存取權,合併授權就會包含這兩個範圍。
- 如果撤銷代表合併授權的權杖,系統會同時撤銷代表相關聯使用者存取該授權所有範圍的權限。
下列程式碼範例說明如何將範圍新增至現有的存取權杖。這種做法可讓應用程式避免管理多個存取權杖。
OAuth 2.0 端點
如要將範圍新增至現有存取權杖,請在向 Google OAuth 2.0 伺服器發出的要求中加入 include_granted_scopes
參數。
下列程式碼片段示範如何執行這項操作。程式碼片段會假設您已將存取權杖有效的範圍儲存在瀏覽器的本機儲存空間。(完整範例程式碼會設定瀏覽器本機儲存空間中的 oauth2-test-params.scope
屬性,儲存存取權杖有效的範圍清單)。
程式碼片段會比較存取權杖有效的範圍,以及您要用於特定查詢的範圍。如果存取權杖未涵蓋該範圍,系統會啟動 OAuth 2.0 流程。
這裡的 oauth2SignIn
函式與步驟 2 中提供的函式相同 (稍後在完整範例中也會提供)。
var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly'; 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 中撤銷權杖,而不使用 JavaScript 適用的 Google API 用戶端程式庫。由於 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(); }
導入跨帳戶防護功能
為保護使用者帳戶,您應採取額外步驟,利用 Google 的跨帳戶保護服務實作跨帳戶保護機制。這項服務可讓您訂閱安全性事件通知,向應用程式提供使用者帳戶重大變更的相關資訊。接著,您就能根據決定如何回應活動,採取適當行動。
Google 跨帳戶保護服務傳送給應用程式的事件類型包括:
-
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
-
https://schemas.openid.net/secevent/oauth/event-type/token-revoked
-
https://schemas.openid.net/secevent/risc/event-type/account-disabled
如要進一步瞭解如何實作跨帳戶保護機制,以及查看可用事件的完整清單,請參閱「 透過跨帳戶保護機制保護使用者帳戶 」頁面。