0
votes

I am trying to run a Google Apps script using the Google Apps Script API method scripts.run. However, I get a 403 error with the following error message:

{
  "error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
  }
}

Here are the headers for the POST request I am sending:

authorization: Bearer my-oauth-token
Content-Type: application/json
Origin: http://localhost:5000
Referer: http://localhost:5000/static/test.html
User-Agent: Mozilla/5.0...

I am sending the request to https://script.googleapis.com/v1/scripts/my_script_id:run?key=my_api_key

Any ideas? I have tried searching for examples, but all I get are ones that you the google apis client libraries, when I need to use the REST api. I know for sure that my oauth tokens are correct, as I make requests to other Google apis with the same token.

This is my current flow:

  1. Redirect user to oauth url, and get exchange code. My redirect url is
"https://accounts.google.com/o/oauth2/v2/auth?"
        "scope=https://www.googleapis.com/auth/drive&"
        "state=%s&"
        "redirect_uri=redirect_uri&"
        "client_id=id&"
        "response_type=code&"
        "access_type=offline&"
        "prompt=consent"
  1. Exchange code for refresh token
  2. Use refresh token to get an oAuth access token. I send a POST request to https://www.googleapis.com/oauth2/v4/token to do this.
  3. I use access token to get thumbnails from a user's google slides. This request succeeds.
  4. I send request to execute Google Apps Script. Here is the summarized code for this request:
xhr.open("POST", "https://script.googleapis.com/v1/scripts/id:run", true);
xhr.setRequestHeader("authorization", "Bearer " + oauth_token);
xhr.onload = function() { // do stuff }
xhr.onerror = function() { // print error }
xhr.send(JSON.stringify({
   "function": "run",
    "parameters": [
       id1,
       id2
    ]
}));

This gives me 401 error. I also get message "Provisional Headers are shown". I looked into that and it does not seem related to my issue.enter image description here

This is the script that I am trying to run:

function doGet(e) {
  if(!(e.parameter.source && e.parameter.destination)) {
    throw new Error("Not all parameters specified");
  }
  copySlides(e.parameter.source, e.parameter.destination);
}

function copySlides(sourceId, destinationId) {
  var src = SlidesApp.openById(sourceId);
  var dest =  SlidesApp.openById(destinationId);

  src.getSlides().forEach(function(slide, index) {
      dest.appendSlide(slide);
  });
  return ContentService.createTextOutput("Done Copying Slides");
}
1
Unfortunately, in the current stage, Google Apps Script API cannot be used by API key and service account, yet. Please use the access token retrieved by OAuth2. I apologize for this situation. - Tanaike
Hmm, I am sending both the oauth token and the API key, if I remove api key I get same error. - chiragzq
Thank you for replying. Although I'm not sure about your script, if you are using the access token, how about removing key=my_api_key? - Tanaike
Thank you for replying. I apologize for the inconvenience. Can you provide your current script and the detail flow for replicating your situation? If you can do, please add it to your question. Of course, please remove your personal information. By the way, your title says the status code of 403 is returned. But in the question, 401 is returned. Can I ask you about this difference? - Tanaike
@spafindoople Unfortunately, I cannot still replicate your situation. I apologize for this situation. When I run your script, it works fine. From the error message, I think that there is the issue at the access token. For example, how about creating new standalone script and deploying it as the execution API. And retrieving client ID and client secret from the project of the deployed script, and then running your script using the retrieved access token. Can you try this? - Tanaike

1 Answers

1
votes

It turns out I was missing an extra oAuth scope, since my script used the Google SlidesApp. Adding https://www.googleapis.com/auth/presentations scope fixed.