使用程式碼模型

使用者可以透過 Google Identity Services 程式庫,使用瀏覽器型快顯視窗或重新導向使用者體驗流程,向 Google 要求授權碼。這會啟動安全的 OAuth 2.0 流程,並產生存取權杖,用於代表使用者呼叫 Google API。

OAuth 2.0 授權碼流程摘要:

  • 在瀏覽器中,Google 帳戶擁有者透過手勢 (例如點選按鈕) 向 Google 要求授權碼。
  • Google 會傳送不重複的授權碼,回應使用者瀏覽器中執行的 JavaScript 網頁應用程式回呼,或使用瀏覽器重新導向直接叫用授權碼端點。
  • 後端平台會代管授權碼端點,並接收授權碼。驗證完成後,系統會向 Google 的權杖端點提出要求,將這個程式碼換成每個使用者的存取權和更新權杖。
  • Google 會驗證授權碼、確認要求來自安全平台、核發存取和更新權杖,並呼叫平台代管的登入端點,傳回權杖。
  • 登入端點會收到存取和更新權杖,並安全地儲存更新權杖,以供日後使用。

必要條件

按照「設定」一文所述的步驟,設定 OAuth 同意畫面、取得用戶端 ID,並載入用戶端程式庫。

初始化程式碼用戶端

google.accounts.oauth2.initCodeClient() 方法會初始化程式碼用戶端。

您可以選擇使用「重新導向」或「彈出式視窗」模式使用者流程,分享授權碼。在重新導向模式中,您會在伺服器上代管 OAuth2 授權端點,Google 會將使用者代理程式重新導向至這個端點,並以網址參數的形式分享授權碼。如果是「彈出式」模式,您要定義 JavaScript 回呼處理常式,將授權碼傳送至伺服器。彈出式模式可提供流暢的使用者體驗,訪客不必離開網站。

如要初始化下列項目的用戶端:

  • 重新導向 UX 流程,將 ux_mode 設為 redirect,並將 redirect_uri 的值設為您平台的授權碼端點。這個值必須與您在 Google Cloud 控制台中設定的 OAuth 2.0 用戶端其中一個已授權重新導向 URI 完全相符。且必須符合重新導向 URI 驗證規則

  • 彈出式視窗使用者體驗流程:將 ux_mode 設為 popup,並將 callback 的值設為您用來將授權碼傳送至平台的函式名稱。redirect_uri 的值預設為呼叫 initCodeClient 的網頁來源。這個值稍後會在流程中用於將授權碼換成存取或更新權杖。舉例來說,https://www.example.com/index.html 會呼叫 initCodeClient,而來源:https://www.example.comredirect_url 的值。

防範 CSRF 攻擊

為防範跨網站偽造要求 (CSRF) 攻擊,重新導向和彈出式視窗模式的 UX 流程會採用稍微不同的技術。如果是「重新導向」模式,則會使用 OAuth 2.0 state 參數。如要進一步瞭解如何產生及驗證 state 參數,請參閱 RFC6749 第 10.12 節「Cross-Site Request Forgery」(跨網站要求偽造)。在彈出式視窗模式中,您可以將自訂 HTTP 標頭新增至要求,然後在伺服器上確認標頭是否符合預期值和來源。

選擇 UX 模式,查看顯示授權碼和 CSRF 處理方式的程式碼片段:

重新導向模式

初始化用戶端,讓 Google 將使用者的瀏覽器重新導向至您的驗證端點,並以網址參數的形式分享授權碼。

const client = google.accounts.oauth2.initCodeClient({   client_id: 'YOUR_CLIENT_ID',   scope: 'https://www.googleapis.com/auth/calendar.readonly',   ux_mode: 'redirect',   redirect_uri: 'https://oauth2.example.com/code',   state: 'YOUR_BINDING_VALUE' }); 

在使用者於彈出式對話方塊中啟動授權流程時,初始化用戶端。使用者同意後,Google 會使用回呼函式,將授權碼傳回使用者的瀏覽器。來自 JS 回呼處理常式的 POST 要求會將授權碼傳送至後端伺服器上的端點,系統會先驗證授權碼,然後完成其餘的 OAuth 流程。

const client = google.accounts.oauth2.initCodeClient({   client_id: 'YOUR_CLIENT_ID',   scope: 'https://www.googleapis.com/auth/calendar.readonly',   ux_mode: 'popup',   callback: (response) => {     const xhr = new XMLHttpRequest();     xhr.open('POST', "https://oauth2.example.com/code", true);     xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');     // Set custom header for CRSF     xhr.setRequestHeader('X-Requested-With', 'XmlHttpRequest');     xhr.onload = function() {       console.log('Auth code response: ' + xhr.responseText);     };     xhr.send('code=' + response.code);   }, }); 

觸發 OAuth 2.0 授權碼流程

呼叫程式碼用戶端的 requestCode() 方法,觸發使用者流程:

<button onclick="client.requestCode();">Authorize with Google</button> 

這樣一來,使用者必須先登入 Google 帳戶並同意分享個別範圍,系統才會將授權碼傳回重新導向端點或回呼處理常式。

驗證碼處理

Google 會為每位使用者產生專屬授權碼,您會在後端伺服器上收到並驗證該授權碼。

如果是「彈出式視窗」模式,使用者瀏覽器中執行的 callback 指定處理常式,會將授權碼轉送至平台代管的端點。

如果是「重新導向」模式,系統會將 GET 要求傳送至 redirect_uri 指定的端點,並在網址 code 參數中分享授權碼。如要接收授權碼,請按照下列步驟操作:

  • 如果沒有現有實作項目,請建立新的授權端點,或

  • 更新現有端點,接受 GET 要求和網址參數。先前是使用酬載中含有授權碼值的 PUT 要求。

授權端點

授權碼端點必須處理含有下列網址查詢字串參數的 GET 要求:

名稱
authuser 要求使用者登入驗證
程式碼 Google 產生的 OAuth2 授權碼
HD 高畫質 使用者帳戶的代管網域
提示詞 使用者同意聲明對話方塊
範圍 以空格分隔的一或多個要授權的 OAuth2 範圍清單
CRSF 狀態變數

以下是 GET 要求範例,其中包含傳送至名為 auth-code 的端點,且由 example.com 代管的網址參數:

Request URL: https://www.example.com/auth-code?state=42a7bd822fe32cc56&code=4/0AX4XfWiAvnXLqxlckFUVao8j0zvZUJ06AMgr-n0vSPotHWcn9p-zHCjqwr47KHS_vDvu8w&scope=email%20profile%20https://www.googleapis.com/auth/calendar.readonly%20https://www.googleapis.com/auth/photoslibrary.readonly%20https://www.googleapis.com/auth/contacts.readonly%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&authuser=0&hd=example.com&prompt=consent 

如果授權碼流程是由較早的 JavaScript 程式庫啟動,或是直接呼叫 Google OAuth 2.0 端點,則會使用 POST 要求。

以下是 POST 要求範例,其中授權碼會以酬載形式放在 HTTP 要求主體中:

Request URL: https://www.example.com/auth-code Request Payload: 4/0AX4XfWhll-BMV82wi4YwbrSaTPaRpUGpKqJ4zBxQldU\_70cnIdh-GJOBZlyHU3MNcz4qaw 

驗證要求

請在伺服器上執行下列操作,避免發生 CSRF 攻擊。

檢查重新導向模式的 state 參數值。

確認 X-Requested-With: XmlHttpRequest 標頭已設為彈出式視窗模式。

只有在您先成功驗證授權碼要求後,才應繼續從 Google 取得重新整理和存取權杖。

取得存取和更新權杖

後端平台收到 Google 傳送的授權碼並驗證要求後,請使用授權碼向 Google 取得存取和更新權杖,以便發出 API 呼叫。

按照使用 OAuth 2.0 處理網路伺服器應用程式」指南中的「步驟 5:將授權碼換成重新整理和存取權杖」操作。

管理權杖

平台會安全儲存重新整理權杖。移除使用者帳戶或使用者透過 google.accounts.oauth2.revoke 或直接從 https://myaccount.google.com/permissions 撤銷同意聲明時,請刪除儲存的重新整理權杖。

您也可以考慮使用 RISC 透過跨帳戶保護功能保護使用者帳戶

一般來說,後端平台會使用存取權杖呼叫 Google API。如果您的網路應用程式也會直接從使用者的瀏覽器呼叫 Google API,您必須實作一種方法,與網路應用程式共用存取權杖,但這超出本指南的範圍。採用這種做法並使用 適用於 JavaScript 的 Google API 用戶端程式庫時,請使用 gapi.client.SetToken() 將存取權杖暫時儲存在瀏覽器記憶體中,並啟用程式庫來呼叫 Google API。