Autorisations de l'API Google Apps Script pour DriveApp.getFileById

Oct 07 2020

J'ai un projet Google Cloud Platform (GCP) qui exécute presque tous les scripts / fonctions directement, mais quelques-uns via une API. Tout n'est accessible qu'en interne au domaine G Suite, et le type d'application de l'écran de consentement OAuth est "Interne".

J'ai un script, qui n'est pas appelé via une API, mais directement sur une minuterie toutes les x minutes. Il effectue un

DriveApp.getFileByID(pictureID)

Cela fonctionne très bien! Pas de problème.

J'ai également un script différent, dans le même projet GCP, qui au lieu de s'exécuter déclenché par un minuteur, s'exécute en étant appelé via une API. Voici la ligne de code qui l'appelle (pas vraiment important):

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

Le script API fonctionne très bien! Jusqu'à ce qu'il atteigne les lignes suivantes:

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

Le résultat du journal est

e = {"name":"Exception"}

J'ai vérifié que le pictureID est le même que dans le script non API qui fonctionne. Je fais un "essai" dans ce script exécuté par l'API pour m'assurer que le logiciel a accès au fichier, pas pour y accéder réellement.

Je suis presque sûr qu'il s'agit d'un problème d'autorisation. J'utilise GCP depuis peu de temps maintenant, j'ai une certaine expérience des autorisations, mais pas beaucoup.

Voici quelques détails autour des autorisations ...

Les scripts du projet Propriétés du projet (Propriétés du fichier / projet) indiquent qu'il a besoin des étendues OAuth suivantes:

Selon la documentation de 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

Voici les champs d'application que j'ai définis maintenant sur l'écran de consentement de GCP Oauth:

Comme vous pouvez le voir, j'ai ajouté drive, drive.readonly et drive.file (ce qui ne semble pas vraiment nécessaire).

En plus de tout cela, ce fichier image particulier est stocké dans le Google Drive du propriétaire du projet GCP, des scripts et de l'administrateur de premier niveau du domaine G Suite. Ce ne sera pas toujours le cas, car les utilisateurs partageront des images de leur propre Google Drive avec ce propriétaire de logiciel / GCP. Cependant, j'ai le sentiment que même maintenant, le script déclenché par un minuteur fonctionnerait avec ces fichiers partagés par l'utilisateur, mais pas le script appelé via une API.

Je suis presque sûr qu'il s'agit d'un problème d'authentification, mais il me manque quelque chose quelque part.

Merci de votre aide!

Mettre à jour:

Voici le code du script qui APPELLE le script API (en a changé pour la confidentialité), car je me demande si le problème n'est peut-être pas du côté client / appelant. Peut-être que je ne reçois pas correctement le OAuthToken? Ou le jeton n'a pas les autorisations appropriées?

  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);

Réponses

Chris Oct 07 2020 at 22:27

Je l'ai compris après avoir contacté Google, et malheureusement pas beaucoup d'aide, et quelques heures supplémentaires d'essais et de recherches ...

Ce qui me manquait, c'était d'ajouter «oathScopes» au fichier manifest / appsscript.json. J'ai joué avec les portées nécessaires et j'ai fini avec les deux suivantes illustrées ci-dessous. J'ai trouvé la solution en regardant cette réponse: Utiliser AuthToken obtenu via ScriptApp.getAuthToken () pour appeler des applications Web dans GAS .

Dans l'éditeur de script, accédez à Afficher / Afficher le fichier manifeste.

Voici à quoi cela ressemblait avant:

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

et voici à quoi ça ressemble maintenant ...

{
  "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"
    ]
}

Après avoir ajouté, j'ai enregistré appsscript.json. Je suis ensuite allé à mon déclencheur runOnEdit (le script d'appel), je l'ai supprimé et ajouté de nouveau. Cependant, cela a causé une erreur de recherche désagréable:

J'ai recherché cela et j'ai trouvé ce message: Erreur de réception lors de la création d'un nouveau déclencheur sur Apps Script . Donc, j'ai exécuté le code dans l'éditeur de script, et en effet il a fait apparaître l'écran d'authentification. J'ai approuvé, rajouté le déclencheur, et maintenant tout fonctionne très bien pour appeler l'API!