0

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");
}
TheMaster
  • 45,448
  • 6
  • 62
  • 85
chiragzq
  • 388
  • 1
  • 14
  • 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 Apr 11 '19 at 04:55
  • Hmm, I am sending both the oauth token and the API key, if I remove api key I get same error. – chiragzq Apr 11 '19 at 04:56
  • 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 Apr 11 '19 at 04:57
  • Yeah I just tried that, I get the same error :( – chiragzq Apr 11 '19 at 04:57
  • 1
    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 Apr 11 '19 at 05:04
  • Sorry, I made error when I was writing title :(. I edited my post with basic flow. If you need more information I can give more. – chiragzq Apr 11 '19 at 05:35
  • Your client code meets all the requirements to use the execution API, correct? https://developers.google.com/apps-script/api/how-tos/execute#requirements – tehhowch Apr 11 '19 at 05:45
  • Yup -- I have re-checked this just now. – chiragzq Apr 11 '19 at 06:04
  • @spafindoople Unfortunately, I couldn't replicate your situation from your script. I would like to confirm your situation. The status code you got is 401 (it's not 403.). Is this correct? If this is correct, it is possible to be the wrong access token. Was your access token was retrieved by OAuth2 process? Can I ask you about the length of the access token? – Tanaike Apr 11 '19 at 06:06
  • @spafindoople And also, was your access token was retrieved from the client ID and client secret of the project binding to the script you want to run? If the client ID and client secret of the project without binding to the script you want to run are used, the status code of 403 is returned. When the status code of 401 is returned, the access token means wrong. How about this? – Tanaike Apr 11 '19 at 06:10
  • Here is the basic structure of the oauth token that I am sending: `ya29.aaa_aaa_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`. I just double checked, I am generating oauth token with the same google cloud project as the one the script is associated with. I just ran a slides api request with the oauth token and it was successful, so I think oauth access token is correct. – chiragzq Apr 11 '19 at 06:23
  • 1
    @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 Apr 11 '19 at 06:39
  • Your redirect url is missing scopes. You need `scriptapp` scopes as well as scopes required for the actual script execution. What does your script do? Show your script. – TheMaster Apr 11 '19 at 09:03
  • Have you deployed your script as a API? – TheMaster Apr 11 '19 at 09:50
  • Thank you everyone so much for your help. @TheMaster, I could not find an oauth scope for `scriptapp`. However, I have edited my question with the script that I am running. I am sure that I have deployed my script as an API. @Tanaike, I will try what you have suggested. – chiragzq Apr 11 '19 at 15:09
  • @Tanaike, I just tried it, and it worked. I am guessing that i did not configure something correctly with my original script. I will see if now I can get it working. – chiragzq Apr 11 '19 at 15:26
  • @spafindoople I'm glad your issue was resolved. Thank you for reporting and posting it. – Tanaike Apr 11 '19 at 22:16
  • No, thank you and @TheMaster for all your suggestions! Without them I would not have my solution. – chiragzq Apr 12 '19 at 04:28

1 Answers1

2

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.

chiragzq
  • 388
  • 1
  • 14