DriveApp.getFileByIdのGoogleApps ScriptAPI認証

Oct 07 2020

ほとんどすべてのスクリプト/関数を直接実行するGoogleCloud Platform Project(GCP)がありますが、APIを介していくつか実行します。すべてはGSuiteドメインの内部でのみアクセス可能であり、OAuth同意画面のアプリケーションタイプは「内部」です。

APIを介して呼び出されるのではなく、x分ごとにタイマーで直接呼び出されるスクリプトがあります。それは実行します

DriveApp.getFileByID(pictureID)

これはうまくいきます!問題はありません。

また、同じGCPプロジェクトに別のスクリプトがあり、タイマーによってトリガーされて実行されるのではなく、APIを介して呼び出されて実行されます。これを呼び出すコード行は次のとおりです(それほど重要ではありません)。

var result = UrlFetchApp.fetch(url, options);

APIスクリプトはうまく機能します!次の行に到達するまで:

      try { var file = DriveApp.getFileById(pictureID); }
      catch (e) {
        Logger.log('e = ' + JSON.stringify(e));
        return;
      }

ログの結果は次のとおりです。

e = {"name":"Exception"}

pictureIDが、動作する非APIスクリプトの場合と同じであることを確認しました。このAPI実行スクリプトで「試行」を行って、ソフトウェアが実際にファイルにアクセスするのではなく、ファイルにアクセスできることを確認しています。

これは承認の問題であると確信しています。GCPを使用してからしばらく経ちましたが、承認の経験はありますが、それほど多くはありません。

承認に関する詳細は次のとおりです...

プロジェクトのスクリプトプロジェクトプロパティ(ファイル/プロジェクトプロパティ)は、次のOAuthスコープが必要であることを示しています。

Googleのドキュメントによると https://developers.google.com/apps-script/reference/drive/drive-app#getfilebyidid、

Scripts that use this method require authorization with one or more of the following scopes: 

https://www.googleapis.com/auth/drive.readonly
https://www.googleapis.com/auth/drive

GCPOauth同意画面で定義したスコープは次のとおりです。

ご覧のとおり、drive、drive.readonly、およびdrive.fileを追加しました(実際には必要ないようです)。

さらに、この特定の画像ファイルは、GCPプロジェクトの所有者のGoogleドライブ、スクリプト、GSuiteドメインのトップレベルの管理者に保存されます。ユーザーは自分のGoogleドライブからこのソフトウェア/ GCPの所有者に画像を共有するため、常にそうなるとは限りません。ただし、タイマーによってトリガーされたスクリプトは、これらのユーザー共有ファイルでは機能しますが、APIを介して呼び出されたスクリプトでは機能しないと感じています。

これは認証の問題であると確信していますが、どこかに何かが足りません。

ご協力ありがとうございました!

更新:

これは、APIスクリプトを呼び出すスクリプトのコードです(機密性のために一部変更されています)。おそらく問題がクライアント/呼び出し側にあるのではないかと思います。おそらく、OAuthTokenを正しく取得していませんか?または、トークンに正しい権限がありませんか?

  var token = ScriptApp.getOAuthToken();
  
  var header = {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + token,
  };
  
  var parms = [id];
  
  var data = {
    "function": "updateSettings",
    "parameters": parms,
    "devMode": true,
  }
  
  var options = {
    "method":"POST",
    "headers": header,
    "muteHttpExceptions": true,
    "payload": JSON.stringify(data)
  };
  
  // Call the API
  var result = UrlFetchApp.fetch(url, options);

回答

Chris Oct 07 2020 at 22:27

グーグルに連絡した後、私はそれを理解しました、そして残念ながらあまり助けを得られませんでした、そしてさらに数時間の試みと研究...

私が見逃していたのは、manifest /appsscript.jsonファイルに「oathScopes」を追加することでした。必要なスコープをいじってみたところ、以下の2つになりました。私はこの答えを見て解決策を見つけました:ScriptApp.getAuthToken()を介して取得したAuthTokenを使用してGASのWebアプリを呼び出します。

スクリプトエディタ内で、マニフェストファイルの表示/表示に移動します。

以前は次のようになりました。

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "webapp": {
    "access": "MYSELF",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

これが今の様子です...

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "webapp": {
    "access": "MYSELF",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/script.external_request"
    ]
}

追加した後、appsscript.jsonを保存しました。次に、runOnEditトリガー(呼び出し元のスクリプト)に移動し、それを削除して再度追加しました。しかし、それは厄介な見た目のエラーを引き起こしました:

私はそれを調べて、この投稿を見つけました:AppsScriptで新しいトリガーを作成するときにエラーを受け取ります。そこで、スクリプトエディターでコードを実行すると、実際に認証画面が表示されました。承認し、トリガーを再度追加しました。これで、APIの呼び出しですべてがうまく機能します。