使用符記模型

google.accounts.oauth2 JavaScript 程式庫可協助您提示使用者 並取得用來處理使用者資料的存取權杖。這種出價方式是根據 OAuth 2.0 隱含授權流程,可讓您藉由 API 直接使用 REST 和 CORS,或將 Google API 用戶端程式庫用於 JavaScript (也稱為 gapi.client) 可用來輕鬆靈活存取我們的 以及更加複雜的 API

網站使用者先從瀏覽器存取受保護的使用者資料 Google 的網頁式帳戶選擇工具、登入和同意聲明程序,以及 Google 的 OAuth 伺服器問題,並將存取權杖傳回網頁應用程式。

在權杖式授權模型中,不需要為每位使用者儲存 更新憑證

建議您採用本文說明的方法,而非 舊版用戶端網頁應用程式適用的 OAuth 2.0 指南。

設定

按照取得 Google API 用戶端 ID 指南。接著,請在頁面中新增用戶端程式庫 以便呼叫 Google API最後,初始化權杖 用戶端。通常,這項作業是在用戶端程式庫的 onload 處理常式內完成。

初始化權杖用戶端

呼叫 initTokenClient(),使用網頁應用程式的 用戶端 ID,您可以視需要納入一或多個使用者範圍清單 需要存取權:

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (response) => {
    ...
  },
});

觸發 OAuth 2.0 權杖流程

使用 requestAccessToken() 方法觸發權杖使用者體驗流程,並取得 存取權杖Google 會提示使用者執行下列操作:

  • 選擇孩子的帳戶
  • 登入 Google 帳戶 (如果尚未登入)。
  • 同意讓網頁應用程式存取每個要求的範圍。

使用者手勢觸發了權杖流程:<button onclick="client.requestAccessToken();">Authorize me</button>

接著,Google 會傳回 TokenResponse,其中包含存取權杖和 使用者授予回呼處理常式存取權的範圍,或者發生錯誤。

使用者如果關閉帳戶選擇工具或登入視窗, 不會叫用回呼函式。

應用程式的設計和使用者體驗只有在 全面詳閱 Google 的 OAuth 2.0 政策。這些政策涵蓋 使用多個範圍、處理使用者同意聲明的時機和方式等等

漸進式授權是一種政策和應用程式設計方法,用於評估 只在必要時使用範圍 (而非預先) 要求資源的存取權 而且能一次顯示所有內容使用者可以核准或拒絕個別資源的共用要求 也就是精細權限

在這個過程中,Google 會提示使用者同意聲明,請分別列出每個提示 要求的範圍,使用者選取要與應用程式共用的資源 最後,Google 會叫用您的回呼函式,以傳回存取權杖和使用者 或通過核准的範圍接著,您的應用程式就能安全地處理各種不同結果 提供權限和權限

漸進式授權

針對網頁應用程式,以下兩個概略情境示範了 授權使用:

  • 單頁 Ajax 應用程式,通常使用具有動態存取權的 XMLHttpRequest 再複習一下,機構節點 是所有 Google Cloud Platform 資源的根節點
  • 如果有多個網頁,資源會依個別頁面分隔及管理。

這兩種情境是為了說明設計注意事項並 但並未提供完整的建議 在應用程式中建立同意聲明實際應用程式可以使用變化版本或 可以結合這些技術

Ajax

您可以透過發出多次呼叫,為應用程式新增漸進式授權的支援 傳送至 requestAccessToken(),並使用 OverridableTokenClientConfig 物件的 scope 參數,在需要時要求個別範圍,以及 只在必要時使用這個範例資源將要求並顯示 只有在使用者手勢展開收合內容部分後才會觸發。

Ajax 應用程式
在網頁載入時初始化權杖用戶端:
        const client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_GOOGLE_CLIENT_ID',
          callback: "onTokenResponse",
        });
      
敬上 透過使用者手勢來徵求同意,並取得存取權杖 按一下 `+` 即可開啟:

要閱讀的文件

顯示最近的文件

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/documents.readonly'
             })
           );
        

近期活動

顯示日曆資訊

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/calendar.readonly'
             })
           );
        

顯示相片

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/photoslibrary.readonly'
             })
           );
        

每次對 requestAccessToken 的呼叫都會觸發使用者同意聲明時刻,您的應用程式會 只能存取使用者所選部分中所需的資源 因此透過使用者選擇限制資源共享。

多個網頁

設計漸進式授權時,會使用多個頁面 只載入網頁所需的範圍,可降低複雜度, 進行多次呼叫來取得使用者同意聲明,並擷取存取權杖。

多頁面應用程式
網頁 程式碼
第 1 頁:要閱讀的文件
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/documents.readonly',
  });
  client.requestAccessToken();
          
第 2 頁:近期活動
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/calendar.readonly',
  });
  client.requestAccessToken();
          
第 3 頁:相片輪轉介面
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/photoslibrary.readonly',
  });
  client.requestAccessToken();
          

每個網頁都會要求必要的範圍,並透過呼叫 載入時間:initTokenClient()requestAccessToken()。在這個情境中 個別網頁會利用清楚區分使用者功能 來部署資源在實際情況下,個別頁面可能會要求存取 有多個相關範圍

精細權限

在所有情況下,精細權限的處理方式都相同;晚於 requestAccessToken() 會叫用回呼函式和存取權杖 則會傳回,檢查使用者已使用以下應用程式核准要求的範圍: hasGrantedAllScopes()hasGrantedAnyScope()。例如:

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly \
          https://www.googleapis.com/auth/documents.readonly \
          https://www.googleapis.com/auth/photoslibrary.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      if (google.accounts.oauth2.hasGrantedAnyScope(tokenResponse,
          'https://www.googleapis.com/auth/photoslibrary.readonly')) {
        // Look at pictures
        ...
      }
      if (google.accounts.oauth2.hasGrantedAllScopes(tokenResponse,
          'https://www.googleapis.com/auth/calendar.readonly',
          'https://www.googleapis.com/auth/documents.readonly')) {
        // Meeting planning and review documents
        ...
      }
    }
  },
});

先前在先前工作階段或要求中接受的任何授予項目,也都會 其他類別。系統會為個別使用者保存使用者同意聲明記錄; Client ID,且會在多次呼叫 initTokenClient()requestAccessToken()。根據預設,您只需要取得使用者同意聲明, 每次使用者造訪網站並要求新範圍時, 每次載入網頁時都在權杖用戶端設定物件中使用 prompt=consent

使用權杖

在權杖模型中,OS 或瀏覽器不會儲存存取權杖, 系統會在網頁載入時首次取得新權杖,或等到載入完成後再觸發 透過使用者手勢 (例如按下按鈕) 呼叫 requestAccessToken()

將 REST 和 CORS 與 Google API 搭配使用

藉由存取權杖,您可以採用 REST 和 CORS這可讓使用者登入帳戶、同意授權、讓 Google 核發 存取權杖和您的網站,以便處理使用者資料。

在這個範例中,要查看已登入帳戶的使用者即將進行的日曆活動,請使用 tokenRequest() 傳回的存取權杖:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.access_token);
xhr.send();

詳情請參閱如何使用 CORS 存取 Google API

下一節將說明如何輕鬆整合更複雜的 API。

使用 Google API JavaScript 程式庫

憑證用戶端適用於 JavaScript 適用的 Google API 用戶端程式庫 請參閱下方的程式碼片段。

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      gapi.client.setApiKey('YOUR_API_KEY');
      gapi.client.load('calendar', 'v3', listUpcomingEvents);
    }
  },
});

function listUpcomingEvents() {
  gapi.client.calendar.events.list(...);
}

權杖到期

在設計上,存取權杖的生命週期很短。如果存取權杖過期 並在使用者工作階段結束前,呼叫 requestAccessToken() (按下按鈕等使用者導向事件)。

呼叫 google.accounts.oauth2.revoke 方法即可移除使用者同意聲明, 可存取應用程式所授予所有範圍的資源。有效的存取權 需要憑證才能撤銷這項權限:

google.accounts.oauth2.revoke('414a76cb127a7ece7ee4bf287602ca2b56f8fcbf7fcecc2cd4e0509268120bd7', done => {
    console.log(done);
    console.log(done.successful);
    console.log(done.error);
    console.log(done.error_description);
  });