【问题标题】:How to authorize scope for GAS to edit Google Spreadsheets如何授权 GAS 编辑 Google 电子表格的范围
【发布时间】:2020-07-17 20:28:45
【问题描述】:

我有一个调用 Google App Script 函数的 Powershell 脚本。

当我运行 Powershell 脚本时,我可以在我的 GCP 项目的错误报告中看到以下错误:

Exception: You do not have permission to call SpreadsheetApp.getActiveSpreadsheet. Required permissions: (https://www.googleapis.com/auth/spreadsheets.currentonly || https://www.googleapis.com/auth/spreadsheets)
at toSpreadsheet (Código:3)
at fromPS (Código:14)

我知道我必须授权范围,所以我一直在尝试通过编辑清单文件来做到这一点。

Authorization Scopes Documentation 说,

“在授权流程中,Apps 脚本向用户提供所需范围的可读描述。例如,如果您的脚本需要对电子表格的只读访问权限,则清单可能具有范围 @987654322 @. 在授权流程中,具有此范围的脚本会要求用户允许此应用程序“查看您的 Google 电子表格”。”

在我的例子中,我编辑了清单文件 appscript.json 以添加范围 https://www.googleapis.com/auth/spreadsheets,然后我保存它,将 Google App Script 项目发布为 API Executable,最后我再次运行 Powershell 代码,但我仍然得到与上述相同的错误。在所有这些流程中,我没有被要求允许任何事情。我无法理解授权脚本拥有所需权限时缺少什么。

我还将电子表格范围添加到 OAuth 同意屏幕,但它似乎没有任何区别。我怀疑我应该使用服务帐户来完成此操作,因为我看不到通过 OAuth 客户端验证的方法,因为我在 Google 上的脚本是从 Powershell 脚本调用的。我不想相信这一点,因为了解如何配置 OAuth2 花了我很多时间:(

一些注意事项:

  1. 当我直接从 Google 脚本编辑器运行时,Powershell 的 run 方法调用的函数运行良好。

  2. 脚本项目部署为 API 可执行文件

  3. 在 GCP 项目中启用了 Google Apps Script API

  4. 它与标准 GCP 项目相关联

  5. OAuth 凭据是 Web 应用程序类型

  6. 从 Powershell 向 Google 表格写入和读取值的脚本运行良好

谷歌脚本:

function toSpreadsheet(text2write)
  { 
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("HIL_APP");
  var LastRow = sheet.getLastRow();

  for (var i = 1; i < LastRow; i++)
  {
    sheet.getRange(i+1, 8, 1).setValue(text2write)
  }
  return "myreturn"
}

function fromPS(params)
{
  Logger.log(params) 
  var rtn = toSpreadsheet(params)
  return rtn
}

清单文件:

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/spreadsheets"
  ],  
  "timeZone": "America/Argentina/Buenos_Aires",
  "dependencies": {
  },
  "webapp": {
    "access": "ANYONE",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "executionApi": {
    "access": "MYSELF"
  },
  "runtimeVersion": "V8"
}

Powershell 代码:

function doit{
    $json = ".\client_id.json"
    $jdata = get-content $json | convertfrom-json
    <#
    $jdata | ForEach-Object {
        $_.PSObject.Properties.Value
    }
    #>
    $ClientID = $jdata.web.client_id.ToString()
    $ClientSecret = $jdata.web.client_secret.ToString()
    $refreshToken = "1//04VvG_FTyDGhiCgYIARAAGAQSNwF-L9IrZ-o1kaZQQccvzL5m4TUTNz6b9Q4KCb16t4cH11gGCshWZWvgaCoMlg73FgpLAGOYTEk" 
    $grantType = "refresh_token" 
    $requestUri = "https://accounts.google.com/o/oauth2/token" 
    $GAuthBody = "refresh_token=$refreshToken&client_id=$ClientID&client_secret=$ClientSecret&grant_type=$grantType" 
    $GAuthResponse = Invoke-RestMethod -Method Post -Uri $requestUri -ContentType "application/x-www-form-urlencoded" -Body $GAuthBody


    $accessToken = $GAuthResponse.access_token

    $headers = @{"Authorization" = "Bearer $accessToken"          

                  "Content-type" = "application/json"}

    $spreadsheetId = "1htbeGlqZ4hojQBWl9fxE4nW_KZI9uVwi0ApzNOIbwnY"

    $currentDate = (Get-Date).ToString('MM/dd/yyyy')
    $currentTime = (Get-Date).ToString('HH:mm:sstt')

$json = @”
{
    "range": "HIL_APP!A1:G1",
    "majorDimension": "ROWS",
    "values":
                [[
                    "HIL_NAME",
                    "$env:ComputerName",
                    "$currentDate",
                    "$currentTime",
                    "$env:UserName",
                    "input from user",
                    "attempt"
                ],]
}
“@

    $write = Invoke-WebRequest -Uri "https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/HIL_APP!A1:G1:append?valueInputOption=USER_ENTERED" -Method Post -ContentType "application/json" -Body $json  -Headers @{"Authorization"="Bearer $accessToken"}
    $read = Invoke-WebRequest -Uri "https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/HIL_APP!A1:G1" -Headers @{"Authorization"="Bearer $accessToken"}
    $read
    Write-Output "read: " ($read.Content | ConvertFrom-Json)

    $scriptId = "1eF7ZaHH-pw2-AjnRVhOgnDxBUpfr0wALk1dVFg7B220bg_KuwVudbALh"          

$json = @"
{
  "function": "fromPS",
  "parameters": ["myparam"],
  "devMode": true
}
"@

$resp = Invoke-WebRequest -Uri "https://script.googleapis.com/v1/scripts/${scriptId}:run" -Method Post -ContentType "application/json" -Body $json -Headers @{"Authorization"="Bearer $accessToken"}
$resp 
Write-Output "script response: " ($resp.Content | ConvertFrom-Json)
}

$error.Clear()

clear

doit

【问题讨论】:

  • 确保all four requirements 满意
  • 为了正确了解您的情况,您能否提供用于复制您的问题的 Google Apps 脚本?
  • @TheMaster,我从脚本编辑器运行它工作正常。在您共享的链接上,我并不完全理解最后一个要求“确保脚本和调用应用程序共享一个通用的云平台 (GCP) 项目。”这种情况下的调用应用程序是Powershell,对吧?一旦他们使用相同的 ClientID,那么这个要求就满足了。我说的对吗?
  • @Tanaike,我已经确认 App Script API 的设置工作正常,方法是修改我的谷歌脚本以返回单个字符串,并且 powershell 能够读取这个字符串作为来自谷歌脚本的响应。
  • 感谢您的回复。如果设置完成,当ScriptApp.getOAuthToken()运行时,会返回一个访问令牌。从您的回复中,虽然我不确定您的实际情况,但我可以理解它没有返回访问令牌。在这种情况下,当运行返回ok 的简单脚本时,您的powershell 脚本是否有效?

标签: powershell google-apps-script google-cloud-platform oauth-2.0 google-apps-script-api


【解决方案1】:

为了使用 Apps Script API 运行 Google Apps Script (GAS) 的功能,需要进行一些复杂的设置。在这种情况下,我想建议测试运行 GAS 功能如下。这个流程可能太小心了。

流程:

  1. 将云平台项目链接到 Google Apps 脚本项目。 Ref
  2. 安装以使用 Apps Script API 中的 scripts.run 方法运行 GAS 功能。 Ref
  3. 将要运行的脚本放入 Google Apps Script 的脚本编辑器中。
    • 在这里,请通过脚本编辑器运行该函数,并确认脚本是否有效。这样就可以避免脚本的问题。
  4. 将以下脚本用于测试运行。这用于 Apps Script API 的第一次测试。

    function test() {
      return "ok";
    }
    
  5. 放置以下示例脚本以检索访问令牌。这用于测试它。请在脚本编辑器中运行它,并复制返回的访问令牌。

    function getToken() {
      Logger.log(ScriptApp.getOAuthToken());
    }
    
  6. 测试以使用检索到的访问令牌运行test() 的 GAS 功能。在这种情况下,通过替换$accessToken = $GAuthResponse.access_token来使用powershell的脚本。

    • 发生错误时,请确认 Apps Script API 的设置。在这种情况下,可以说 GAS 脚本是正确的。
    • 当没有错误发生时,请测试运行你想运行的功能。在这种情况下,所需的范围已包含在访问令牌中。这样就可以避免范围问题。
  7. 当上述测试完成并且您使用 Apps Script API 的脚本工作时,请使用范围检索刷新令牌。范围可以在脚本编辑器中看到。这样,刷新令牌就可以检索到有效的访问令牌。并且您的脚本可以在本地 PC 上使用。

参考资料:

【讨论】:

  • 我向this question 发布了类似的答案,尽管我的项目假定它在本地运行,而不是在 Google Apps 脚本中运行。我会对您的反馈感兴趣。
  • @Rich Moss 感谢您的评论。如果这有用,我很高兴。
猜你喜欢
  • 2022-11-15
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
  • 2014-12-06
  • 2014-10-28
  • 2015-08-25
相关资源
最近更新 更多