Google Apps Script Error - Authorization is required to perform that action

Viewed 13019

I have created an Apps Script that replaces token in Google Doc. This App Script has been deployed as API Executable. I am able to run a function in the apps script editor without any authorization error. But, it fails sometimes with Authorization error when invoked from my java web application. I get the following error:

{
  "name": "replaceTokensInDoc",
  "done": true,
  "error": {
    "code": 3,
    "message": "ScriptError",
    "details": [
      {
        "@type": "type.googleapis.com/google.apps.script.v1.ExecutionError",
        "errorMessage": "Authorization is required to perform that action.",
        "errorType": "ScriptError"
      }
    ]
  }
}

I have read in multiple places that I need to just run a function in Script Editor and provide permission to solve this issue, but it hasn't helped in my case. When I run a function in the editor, it doesn't even show the authorization dialog, which means it has all the necessary permissions. It only fails sometimes. Could somebody let me know the reason for this strange behavior?

2 Answers

python solution for execute.py sample (https://developers.google.com/apps-script/api/how-tos/execute#step_4_make_the_scriptrun_request)

Basically if the expiry time is less than 361 seconds, then refresh the token

from __future__ import print_function
from googleapiclient import errors
from googleapiclient.discovery import build
#from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file as oauth_file, client, tools
import sys
import datetime

def main():
    """Runs the sample.
    """
    SCRIPT_ID = 'YOUR SCRIPT ID' 

    # Setup the Apps Script API
    SCOPES = [
        'https://www.googleapis.com/auth/script.external_request'
        ,'https://www.googleapis.com/auth/spreadsheets'
        ,'https://www.googleapis.com/auth/drive'
        ,'https://www.googleapis.com/auth/drive.scripts'
        ,'https://www.googleapis.com/auth/userinfo.email'
        ]
    store = oauth_file.Storage('token.json')
    creds = store.get()

    now = datetime.datetime.utcnow()
    secondsDiff = (creds.token_expiry-now).total_seconds()

    print(secondsDiff)
    if secondsDiff < 361:
        http = creds.authorize(Http())
        creds.refresh(http)

    if not creds or creds.invalid:
        flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
        creds = tools.run_flow(flow, store)
    service = build('script','v1',credentials=creds)

    # Create an execution request object.
    request = {"function": "doGet", "parameters": [{"sheetId" : sys.argv[1]}]}

    try:
        # Make the API request.
        response = service.scripts().run(body=request,
                scriptId=SCRIPT_ID).execute()

        if 'error' in response:
            # The API executed, but the script returned an error.

            # Extract the first (and only) set of error details. The values of
            # this object are the script's 'errorMessage' and 'errorType', and
            # an list of stack trace elements.
            error = response['error']['details'][0]
            print("Script error message: {0}".format(error['errorMessage']))

            if 'scriptStackTraceElements' in error:
                # There may not be a stacktrace if the script didn't start
                # executing.
                print("Script error stacktrace:")
                for trace in error['scriptStackTraceElements']:
                    print("\t{0}: {1}".format(trace['function'],
                        trace['lineNumber']))
        #else:
        #    # The structure of the result depends upon what the Apps Script
        #    # function returns. Here, the function returns an Apps Script Object
        #    # with String keys and values, and so the result is treated as a
        #    # Python dictionary (folderSet).
        #    folderSet = response['response'].get('result', {})
        #    if not folderSet:
        #        print('No folders returned!')
        #    else:
        #        print('Folders under your root folder:')
        #        for (folderId, folder) in folderSet.iteritems():
        #            print("\t{0} ({1})".format(folder, folderId))

    except errors.HttpError as e:
        # The API encountered a problem before the script started executing.
        print(e.content)


if __name__ == '__main__':
    main()
Related