GAS『Authorization is Required』の原因と対処法

GAS『Authorization is Required』の原因と対処法

Google Apps Scriptで「Authorization is required(認可が必要です)」が出るのは、スクリプトが要求する権限(スコープ)について、ユーザーがまだ許可していない/許可が無効になった/許可の与え方が誤っているため。初回実行・権限の増減・トリガーやウェブアプリの実行主体の食い違い・Advanced Services/API未有効化・組織ポリシー制限が主因。状況別の確認ポイントと確実に通す手順をまとめる。

エラーの意味と代表メッセージ

Authorization is required to perform that action.
Authorization is required / 認可が必要です
The script requires authorization.
Exception: You do not have permission to call ...

・スクリプトが呼ぶサービスの権限が未承認、もしくはスコープが変わり再同意が必要

発生条件の早見表

□ 初回実行(Spreadsheet/Drive/Gmail等のアクセスをまだ承認していない)
□ スクリプトの権限が増えた(例:Driveアクセスを新たに使い始めた)
□ シンプルトリガー(onEdit/onOpen等)から要認可APIを呼んでいる
□ ウェブアプリの「実行するユーザー」と共有/アクセス設定が不整合
□ Advanced Google servicesや対応API(Cloud Console)が未有効化
□ マニフェストにスコープ未明示 or 組織の許可リスト外のスコープを要求
□ オーナー変更/複製/ライブラリ更新でデプロイが古い版を参照
□ 組織の「信頼できるアプリ」制限でブロックされている

まず確認(最短チェック)

□ エディタの「実行」から任意の関数を走らせ、認可ダイアログが出るか確認
□ プロジェクト設定 → スコープを表示:想定スコープが並んでいるか
□ 実行ログ(Executions)で誰が失敗しているか(実行主体)を確認
□ 「デプロイ」→ ウェブアプリのバージョンと実行ユーザー設定を確認

初回認可/スコープ変更後の再認可を確実に促す

// 認可を確実に促す「フォース認可」用(要認可APIをまとめて一度呼ぶ)
function authorizeOnce() {
  // ここで必要サービスを最低1回は呼ぶ(失敗すれば認可ダイアログ)
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheets()[0];
  sh.getRange(1,1).setValue(new Date()); // Sheets 権限
  DriveApp.getFiles();                    // Drive 権限
  GmailApp.getAliases();                  // Gmail 権限(必要な場合のみ)
  Logger.log('authorized');
}
// 手順:エディタで authorizeOnce() を実行 → ダイアログに同意

・権限を増やした直後は、まずオーナーが上記のような「認可促し関数」を実行して同意を通す

シンプルトリガーではなくインストール型トリガーに切り替える

// シンプルトリガーでは一部サービスを呼べない/再認可が通らないことがある
// → インストール型トリガーに変更して権限を明示的に付与

function job(e) {
  const sh = SpreadsheetApp.getActiveSheet();
  sh.appendRow([new Date(), 'triggered']); // 要認可の処理
}

function installTrigger() {
  ScriptApp.newTrigger('job')
    .forSpreadsheet(SpreadsheetApp.getActive())
    .onEdit() // 例:編集イベント
    .create();
}

・インストール型は作成者の権限で動作。作成者が先に認可しておくこと

ウェブアプリの実行主体・アクセス設定を整える

// ウェブアプリでは以下を確認(「デプロイ」→「新バージョンとしてデプロイ」):
/*
・実行するユーザー:自分(オーナー) or アクセスするユーザー
・アクセスできるユーザー:自分のみ/全員/ドメイン内 等
・変更後は必ず新バージョンで再デプロイ(古い版のままだと認可が噛み合わない)
*/

function doGet(e) {
  return HtmlService.createHtmlOutput('OK');
}

・共有ドライブのファイルにアクセスする場合、実行主体のアカウントに編集権が必要

Advanced Google services / 対応APIを有効化

/*
1) スクリプトエディタ右側「サービス」→ 使う Advanced Google services をON
2) 自動で関連APIが Google Cloud プロジェクトでも有効化される(必要に応じて確認)
3) その後、該当APIを利用する関数を実行して認可ダイアログに同意
*/
function sampleSheetsApi(sheetId) {
  const body = { values: [['A','B'],['C','D']] };
  Sheets.Spreadsheets.Values.update(body, sheetId, 'Data!A1', { valueInputOption: 'USER_ENTERED' });
}

・サービスON前に呼ぶと「Authorization is required」や「Service not found」になりやすい

マニフェストでスコープを明示して同意内容を安定化

// appsscript.json(例)
{
  "timeZone": "Asia/Tokyo",
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/script.external_request" // UrlFetch
  ]
}

・暗黙スコープ任せにせず、必要最小限を明示すると再認可の揺れが減る

組織ポリシー(信頼できるアプリ/許可スコープ)に対応

/*
・Google Workspace 管理コンソールでサードパーティアプリ制限が有効だと、
  個人の同意だけでは通らない。管理者に以下を依頼:
  - スクリプトのクライアントID(デプロイ後に取得)を「信頼できる」へ追加
  - 要求スコープ(Sheets/Drive/Gmail等)を許可
・組織外ユーザーに公開する場合、検証済みアプリ要件に抵触しうる
*/

・組織ポリシーに阻まれている場合はユーザー側では解消できない

実行主体の可視化・再デプロイの徹底

// 誰の権限で動いたか確認(ログで追跡)
function who() {
  console.log({
    effectiveUser: Session.getEffectiveUser().getEmail(), // 実行主体
    activeUser: Session.getActiveUser().getEmail()        // UI操作ユーザー
  });
}

・認可は「誰が実行したか」に結びつく。想定と違う主体で走っていないか確認

よくあるNG→OK(クイック修正)

× スコープ増やしたが再デプロイせず          →  ○ 新バージョンとしてデプロイ→オーナーが先に認可
× onEdit内でGmail/Drive呼び出し               →  ○ インストール型トリガーに変更して作成者が認可
× Webアプリ実行主体を「アクセスユーザー」に   →  ○ 「自分」に変更(必要権限がある主体で実行)
× Advanced ServicesをOFFのまま呼び出し       →  ○ サービスON + API有効化後に認可
× マニフェスト無指定で暗黙スコープ任せ        →  ○ oauthScopesを明示(最小限)

テスト用:認可ガードと詳しい失敗ログ

function runSafely() {
  try {
    // ここで必要サービスを一つずつ呼んで、どこで落ちるかログ
    const ss = SpreadsheetApp.getActive();
    const name = ss.getName(); // Sheets 権限
    console.log('sheet:', name);

    const files = DriveApp.getFiles(); // Drive 権限
    console.log('drive ok?', files.hasNext());

    const res = UrlFetchApp.fetch('https://httpbin.org/get'); // 外部接続
    console.log('fetch code:', res.getResponseCode());

  } catch (e) {
    console.error('auth check failed', { message: e.message, stack: e.stack });
    throw e;
  }
}

・どのAPIで認可不足かを一気に切り分けられる

チェックリスト(上から順に)

□ オーナーが「認可促し関数」を実行して同意を済ませたか
□ スクリプトのスコープが想定どおりか(プロジェクト設定/マニフェスト)
□ ウェブアプリは最新デプロイか(実行主体・アクセス範囲が要件と一致)
□ シンプルトリガーで要認可APIを呼んでいないか(必要ならインストール型へ)
□ Advanced Servicesと対応APIは有効化済みか
□ 実行主体(Session.getEffectiveUser)が想定ユーザーになっているか
□ 組織のアプリ制限/スコープ制限に引っかかっていないか(管理者に確認)