授權範圍

使用者必須授權指令碼專案存取自己的資料,或代為執行操作。當使用者首次執行需要授權的指令碼時,UI 會顯示提示,要求使用者開始授權流程。

在這個流程中,UI 會告知使用者指令碼需要哪些權限。舉例來說,指令碼可能需要讀取使用者的電子郵件訊息,或在日曆中建立活動。指令碼專案會將這些個別權限定義為 OAuth 範圍

對於多數指令碼,Apps Script 會自動偵測所需的範圍;您隨時可以查看指令碼使用的範圍。您也可以使用網址字串,在manifest明確設定範圍。對於外掛程式等特定應用程式,有時需要明確設定範圍,因為已發布的應用程式應一律使用最狹隘的範圍。

在授權流程中,Apps Script 會向使用者顯示必要範圍的說明,讓使用者能輕鬆閱讀。舉例來說,如果指令碼需要對試算表擁有唯讀存取權,資訊清單的範圍可能會是 https://www.googleapis.com/auth/spreadsheets.readonly。在授權流程中,含有此範圍的指令碼會要求使用者允許這個應用程式「查看您的 Google 試算表」。

某些範圍包含其他範圍。舉例來說,授權範圍 https://www.googleapis.com/auth/spreadsheets 可允許使用者讀取及寫入試算表。

在執行指令碼的部分途徑 (例如直接從 Apps Script IDE 執行指令碼),使用者會看到詳細的 OAuth 同意畫面。這樣一來,使用者就能選取要授予的特定權限,而非一次授予所有權限。請務必設計指令碼,以處理精細的 OAuth 權限

檢視範圍

如要查看指令碼專案目前需要的範圍,請按照下列步驟操作:

  1. 開啟指令碼專案。
  2. 按一下左側的「總覽」圖示
  3. 查看「Project OAuth Scopes」下方的範圍。

設定明確的範圍

Apps Script 會掃描程式碼,找出需要函式呼叫的範圍,自動判斷所需的範圍。對於大多數指令碼來說,這就足夠了,而且還能節省您的時間,但如果是已發布的外掛程式、網頁應用程式、Google Chat 應用程式,以及對 Google Chat API 的呼叫,您就必須更直接地控制範圍。

Apps Script 有時會自動為專案指派非常寬鬆的權限範圍。這可能表示指令碼要求使用者提供超出需求的資訊,這是不當做法。對於已發布的指令碼,您必須將廣泛的範圍替換為更受限的範圍,且僅涵蓋指令碼的需求。

您可以編輯指令碼專案的manifest檔案,明確設定指令碼專案使用的範圍。資訊清單欄位 oauthScopes 是專案使用的所有範圍陣列。如要設定專案的範圍,請按照下列步驟操作:

  1. 開啟指令碼專案。
  2. 按一下左側的「專案設定」圖示
  3. 勾選「在編輯器中顯示『appsscript.json』資訊清單檔案」核取方塊。
  4. 按一下左側的「編輯器」圖示
  5. 按一下左側的 appsscript.json 檔案。
  6. 找出標示為 oauthScopes 的頂層欄位。如果沒有,您可以新增。
  7. oauthScopes 欄位會指定字串陣列。如要設定專案使用的範圍,請將這個陣列的內容替換為您要使用的範圍。例如:
          {
            ...
            "oauthScopes": [
              "https://www.googleapis.com/auth/spreadsheets.readonly",
              "https://www.googleapis.com/auth/userinfo.email"
            ],
           ...
          }
  8. 按一下頂端的「」。

處理精細的 OAuth 權限

細部 OAuth 同意畫面可讓使用者指定要授權的個別 OAuth 範圍。精細的 OAuth 權限可讓使用者更精細地控管要與每個指令碼共用的帳戶資料。舉例來說,假設您開發的指令碼要求電子郵件和日曆範圍的權限。使用者可能只想使用您的指令碼,讓 Google 日曆支援特定功能,而非 Gmail。透過精細的 OAuth 權限,使用者可以選擇只授予日曆權限,而非 Gmail 權限。

以下各節將說明處理精細 OAuth 權限的主要方式。

自動要求必要範圍的權限

如果執行流程需要範圍權限才能運作,您可以要求使用者先授予這些權限,才能使用該流程。指令碼可以檢查使用者是否已授予權限,如果尚未授予,則自動要求使用者授予權限。

ScriptApp 類別中的下列方法可讓您驗證必要範圍的權限,並自動顯示授權提示,要求缺少的權限:

範例

以下範例說明如何呼叫 requireScopes(authMode, oAuthScopes)requireAllScopes(authMode) 方法。這個指令碼會使用 Gmail、試算表和日曆的範圍。sendEmail() 函式只需要 Gmail 和試算表的權限,而 createEventSendEmail() 函式則需要指令碼使用的所有權限。

// This function requires the Gmail and Sheets scopes.
function sendEmail() {
  // Validates that the user has granted permission for the Gmail and Sheets scopes.
  // If not, the execution ends and prompts the user for authorization.
  ScriptApp.requireScopes(ScriptApp.AuthMode.FULL, [
    'https://mail.google.com/',
    'https://www.googleapis.com/auth/spreadsheets'
  ]);

  // Sends an email.
  GmailApp.sendEmail("dana@example.com", "Subject", "Body");
  Logger.log("Email sent successfully!");

  // Opens a spreadsheet and sheet to track the sent email.
  const ss = SpreadsheetApp.openById("abc1234567");
  const sheet = ss.getSheetByName("Email Tracker")

  // Gets the last row of the sheet.
  const lastRow = sheet.getLastRow();

  // Adds "Sent" to column E of the last row of the spreadsheet.
  sheet.getRange(lastRow, 5).setValue("Sent");
  Logger.log("Sheet updated successfully!");
}

// This function requires all scopes used by the script (Gmail,
// Calendar, and Sheets).
function createEventSendEmail() {
  // Validates that the user has granted permission for all scopes used by the
  // script. If not, the execution ends and prompts the user for authorization.
  ScriptApp.requireAllScopes(ScriptApp.AuthMode.FULL);

  // Creates an event.
  CalendarApp.getDefaultCalendar().createEvent(
    "Meeting",
    new Date("November 28, 2024 10:00:00"),
    new Date("November 28, 2024 11:00:00")
  );
  Logger.log("Calendar event created successfully!");

  // Sends an email.
  GmailApp.sendEmail("dana@example.com", "Subject 2", "Body 2");
  Logger.log("Email sent successfully!");

  // Opens a spreadsheet and sheet to track the created meeting and sent email.
  const ss = SpreadsheetApp.openById("abc1234567");
  const sheet = ss.getSheetByName("Email and Meeting Tracker")
  // Gets the last row
  const lastRow = sheet.getLastRow();

  // Adds "Sent" to column E of the last row
  sheet.getRange(lastRow, 5).setValue("Sent");
  // Adds "Meeting created" to column F of the last row
  sheet.getRange(lastRow, 6).setValue("Meeting created");
  Logger.log("Sheet updated successfully!");
}

為缺少的範圍建立自訂體驗

您可以取得執行指令碼的使用者權限詳細資料,並根據使用者的權限狀態設計自訂體驗。舉例來說,您可以決定關閉需要使用者未授予權限的特定指令碼功能,或是顯示自訂對話方塊,說明缺少的權限。下列方法會取得包含使用者權限資訊的物件,其中包含使用者已授權的範圍,以及可讓您要求缺少範圍的網址:

如要從授權資訊物件取得權限詳細資料,例如已授權的範圍清單,以及要求缺少權限的網址,請使用 AuthorizationInfo 類別的方法。

範例

以下範例說明如何呼叫 getAuthorizationInfo(authMode, oAuthScopes) 方法,在未授予必要範圍的執行流程中略過特定功能。這樣一來,執行流程的其餘部分就能繼續執行,而不需要提示缺少的範圍授權。

// This function uses the Gmail scope and skips the email
// capabilities if the scope for Gmail hasn't been granted.
function myFunction() {
  const authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL, ['https://mail.google.com/']);
  if (authInfo.getAuthorizationStatus() === ScriptApp.AuthorizationStatus.NOT_REQUIRED) {
    GmailApp.sendEmail("dana@example.com", "Subject", "Body");
    Logger.log("Email sent successfully!");
  } else {
    const scopesGranted = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL).getAuthorizedScopes();
    console.warn(`Authorized scopes: ${scopesGranted} not enough to send mail, skipping.`);
  }
  // Continue the rest of the execution flow...
}

OAuth 驗證

某些 OAuth 範圍屬於機密範圍,因為這些範圍可存取 Google 使用者資料。如果指令碼專案使用可存取使用者資料的範圍,則必須先讓專案通過 OAuth 用戶端驗證,才能公開發布為網路應用程式或外掛程式。詳情請參閱下列指南:

受限制範圍

除了敏感範圍之外,某些範圍也歸類為受限制,並須遵守其他有助於保護使用者資料的規則。如果您打算發布使用一或多個受限制範圍的網路應用程式或外掛程式,應用程式必須遵守所有指定限制,才能發布。

請先查看受限制範圍的完整清單,再嘗試發布。如果您的應用程式使用其中任何一項,則必須在發布前遵守特定 API 範圍附加規定