Google应用脚本执行API服务授权每小时失败一次

时间:2015-10-27 07:23:30

标签: c# google-apps-script google-oauth execution-api

我每隔1.5分钟就用我的C#app执行一次Google应用程序脚本。应用脚本在电子表格和编辑表单之间移动内容。我也使用Drive API。

我的脚本长时间运行良好,除了我每小时收到5分钟的授权错误。

以下是处理授权的代码:

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;

        }

    }
}

我得到这样的服务:

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

但是在一小时结束时,应用程序脚本调用会引发以下错误:

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

为了清楚起见,它可以在其他所有时间运行,而不是在接近结束时的那5分钟内。我确实在我的开发人员控制台上激活了Google Drive API,并且在Resources>下应用程序脚本编辑器中的高级Google服务....

那是怎么回事?这可以解决吗?

3 个答案:

答案 0 :(得分:2)

在进行进一步研究后,我发现只需要从脚本编辑器运行脚本以防止出现此错误。这是我发现的信息:

  

执行该操作需要授权。

     

此错误表示脚本缺少运行所需的授权。在脚本编辑器中运行脚本或从自定义菜单项运行脚本时,将向用户显示授权对话框。但是,当脚本作为服务运行,嵌入了Google协作平台页面或从触发器运行时,无法显示对话框并显示此错误。要授权脚本,请打开脚本编辑器并运行任何功能。要避免此错误,请记住在向脚本添加新服务或功能后,在脚本编辑器中运行一次脚本。

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

我对我的代码做的另一个相关改进是在创建两个服务之前获取凭证对象的新副本:换句话说,我改变了这个:

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

到此:

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

这本身并没有解决我的问题,但它有助于避免OAuth怪癖,并且可以防止不必要的令牌刷新。

答案 1 :(得分:0)

您可能需要刷新令牌。通常来自Google的访问令牌设置为仅3600s(1小时),而刷新令牌的寿命更长,旨在让您在前一个令牌到期时轻松获得新的访问令牌。这可能是一个很好的起点:Google API .NET Client information on token responses

此外,如果您没有刷新令牌,但确实有访问令牌,则可以撤消先前的访问令牌,然后再次进行身份验证。如果正确调用,新响应将具有刷新令牌"确保您获得"Bearer"令牌类型。

有关使用较长的生活刷新令牌here的更多信息。

答案 2 :(得分:0)

如果您的申请失败并且#34;就在接近结束时间的那5分钟内,您很可能遇到this bug with the execution API

显然,使用将在6分钟内到期的令牌向执行API发出请求将提供"需要授权..."错误。这似乎与6分钟是脚本的最长运行时间有关。

解决方法是提前刷新您的令牌,如果您知道它何时到期(在Android上不是这种情况)。希望错误很快得到解决。

我不确定您是否真的能够解决问题,或者您是否找到了一个好的解决方法,但您可能想要解决Apps脚本问题,以便更快地解决问题。