Autorizações da API do Google Apps Script para DriveApp.getFileById

Oct 07 2020

Tenho um projeto do Google Cloud Platform (GCP) que executa quase todos os scripts / funções diretamente, mas alguns por meio de uma API. Tudo está acessível apenas internamente para o domínio do G Suite, e o tipo de aplicativo da tela de consentimento do OAuth é "Interno".

Eu tenho um script, que não é chamado por meio de uma API, mas diretamente em um cronômetro a cada x minutos. Executa um

DriveApp.getFileByID(pictureID)

Isso funciona muito bem! Sem problemas.

Também tenho um script diferente, no mesmo projeto do GCP, que em vez de ser acionado por um temporizador, é executado por meio de uma API. Aqui está a linha de código que o chama (não é muito importante):

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

O script da API funciona muito bem! Até chegar às seguintes linhas:

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

O resultado do log é

e = {"name":"Exception"}

Verifiquei que o pictureID é o mesmo do script não API que funciona. Estou fazendo uma "tentativa" neste script executado por API para ter certeza de que o software tem acesso ao arquivo, não para acessá-lo de fato.

Tenho certeza de que este é um problema de autorização. Eu uso o GCP há pouco tempo, tenho alguma experiência com autorizações, mas não muita.

Aqui estão alguns detalhes sobre as autorizações ...

Os scripts do projeto Propriedades do projeto (Arquivo / Propriedades do projeto) mostram que são necessários os seguintes escopos OAuth:

De acordo com a documentação do Google em 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

Aqui estão os escopos que defini agora na tela de consentimento do GCP Oauth:

Como você pode ver, adicionei drive, drive.readonly e drive.file (que realmente não parece ser necessário).

Além de tudo isso, esse arquivo de imagem específico é armazenado no Google Drive do proprietário do projeto GCP, scripts e administrador de nível superior do domínio do G Suite. Isso nem sempre será o caso, pois os usuários compartilharão imagens de seu próprio Google Drive com este proprietário de software / GCP. No entanto, tenho a sensação de que mesmo agora o script disparado por um cronômetro funcionaria com esses arquivos compartilhados pelo usuário, mas não o script chamado por meio de uma API.

Tenho certeza de que é um problema do Auth, mas estou perdendo algo em algum lugar.

Obrigado pela ajuda!

Atualizar:

Aqui está o código do script que CHAMA o script da API (mudou alguns para confidencialidade), pois estou me perguntando se talvez o problema não esteja no lado do cliente / chamada. Talvez eu não esteja obtendo o OAuthToken corretamente? Ou o token não tem as permissões corretas?

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

Respostas

Chris Oct 07 2020 at 22:27

Descobri isso depois de entrar em contato com o Google e, infelizmente, não obtendo muita ajuda e mais algumas horas de tentativas e pesquisas ...

O que estava faltando era adicionar "oathScopes" ao arquivo manifest / appsscript.json. Eu brinquei com os escopos necessários e acabei com os dois a seguir mostrados abaixo. Eu descobri a solução olhando para esta resposta: Usando AuthToken obtido via ScriptApp.getAuthToken () para chamar aplicativos da web no GAS .

Dentro do editor de script, vá para Exibir / Mostrar arquivo de manifesto.

Aqui está o que parecia antes:

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

e aqui está o que parece agora ...

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

Depois de adicionar, salvei appsscript.json. Em seguida, fui até o gatilho runOnEdit (o script de chamada), removi e adicionei novamente. No entanto, isso causou um erro de aparência desagradável:

Eu pesquisei e encontrei este post: Recebendo erro ao criar um novo gatilho no Apps Script . Então, executei o código no editor de script e, de fato, ele trouxe a tela de autenticação. Eu aprovei, readicionei a trigger, e agora tudo funciona muito bem na chamada da API!