Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google apps script execution API service authorization fails once per hour

I'm executing a Google apps script with my C# app about once every 1.5 minutes. The apps script moves content between spreadsheets, and edits sheets. I also use the Drive API.

My script runs fine over long periods, except for the fact that I get an authorization errors for 5 minutes every hour.

Here is my code that handles authorization:

class Authentication
{

    public static ScriptService ScriptsAuthenticateOauth(UserCredential credential)
    {
        try
        {

            ScriptService service = new ScriptService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "MyApp",
            });

           return service;
        }
        catch (Exception ex)
        {
            Console.WriteLine(DateTime.Now.ToString("HH:mm") + ": An authentication error occurred: " + ex.InnerException);
            return null;
        }

    }


    public static UserCredential getCredential(string clientId, string clientSecret, string userName)
    {

        string[] scopes = new string[] { DriveService.Scope.Drive,  // view and manage your files and documents
                                         DriveService.Scope.DriveAppdata,  // view and manage its own configuration data
                                         DriveService.Scope.DriveAppsReadonly,   // view your drive apps
                                         DriveService.Scope.DriveFile,   // view and manage files created by this app
                                         DriveService.Scope.DriveMetadataReadonly,   // view metadata for files
                                         DriveService.Scope.DriveReadonly,   // view files and documents on your drive
                                         DriveService.Scope.DriveScripts, // modify your app scripts
                                         ScriptService.Scope.Drive,

                                         "https://www.googleapis.com/auth/spreadsheets",
                                         "https://spreadsheets.google.com/feeds",
                                         "https://docs.google.com/feeds"};  
        return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
                                                                                         , scopes
                                                                                         , userName
                                                                                         , CancellationToken.None
                                                                                         , new FileDataStore("Google.Sheet.Sync.Auth.Store")).Result;
    }

    public static DriveService DriveAuthenticateOauth(UserCredential credential)
    {
        try
        {


            DriveService service = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "MyApp",
            });

            // Console.WriteLine("Auth success");


            return service;
        }
        catch (Exception ex)
        {

            // Console.WriteLine(ex.InnerException);
            Console.WriteLine(DateTime.Now.ToString("HH:mm") + ": An authentication error occurred: " + ex.InnerException);
            return null;

        }

    }
}

I get my services like this:

 var credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
 DriveService driveService = Authentication.DriveAuthenticateOauth(credential);
 ScriptService scriptService = Authentication.ScriptsAuthenticateOauth(credential);

But around the end of the hour, the apps script call throws the following error:

Script error message: Authorization is required to perform that action.

Just to be clear, it works at all other times, just not in those 5 minutes near the end of the hour. I did activate Google Drive API on both my developers console, and under Resources > Advanced Google services... in the apps script editor.

So what is going on? Can this be fixed?

like image 325
Coert Grobbelaar Avatar asked Oct 31 '22 16:10

Coert Grobbelaar


1 Answers

Upon doing further research, I found that the script just needed to be run from the Script Editor to prevent this error. This is the info I found:

Authorization is required to perform that action.

This error indicates that the script is lacking the authorization needed to run. When a script is run in the Script Editor or from a custom menu item an authorization dialog is presented to the user. However, when a script is run as a service, embedded with a Google Sites page, or run from a trigger the dialog cannot be presented and this error is shown. To authorize the script, open the Script Editor and run any function. To avoid this error, remember to run the script once in the Script Editor after adding new services or capabilities to your script.

Source: https://developers.google.com/apps-script/troubleshooting#common_errors

Another related improvement I made to my code, was to fetch a fresh copy of the credentials object before creating each of the 2 services: In other words, I changed this:

var credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
DriveService driveService = Authentication.DriveAuthenticateOauth(credential);
ScriptService scriptService = Authentication.ScriptsAuthenticateOauth(credential);

to this:

var credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
DriveService driveService = Authentication.DriveAuthenticateOauth(credential);
credential = Authentication.getCredential(CLIENT_ID, CLIENT_SECRET, Environment.UserName);
ScriptService scriptService = Authentication.ScriptsAuthenticateOauth(credential);

This by itself did not fix my problem, but it helps with avoiding OAuth quirks, and can prevent unnecessary token refreshes.

like image 179
Coert Grobbelaar Avatar answered Nov 09 '22 07:11

Coert Grobbelaar