Google 云函数:如何在所需范围内获取云函数中的访问令牌?
Google cloud functions: How to get access tokens in cloud function for the required scope?
我们正在偏离数据存储 scheduled export mechanism (google suggested) and adopting to schedule datastore backup via cloud scheduler which will target HTTP cloud function。在这里,我们想使用云功能将我们的数据存储实体导出到某个存储桶。这种偏离标准机制的原因是,我们希望在所有服务中避免重复的非应用程序特定代码。
根据 docs,托管导出和导入服务只能通过数据存储模式管理 API(REST、RPC)使用,并且请求需要 OAuth 2.0 授权。
在云函数中,要访问数据存储 API https://datastore.googleapis.com/v1/projects/<APP ID>:export
,我们需要范围 https://www.googleapis.com/auth/datastore
.
access_token
在标准的 GAE 应用程序代码中,使用 python27 运行时,我们可以按照下面的示例获得 access_token -
from google.appengine import app_identity
access_token, _ = app_identity.get_access_token('https://www.googleapis.com/auth/datastore')
但是,云函数有 Python37 运行时。因此,导入 google.appengine
给出错误 error as error: ModuleNotFoundError: No module named 'google.appengine'
我们如何获得所需范围的 access_token
? (以下范围之一)-
建议参考Python code/document。谢谢。
Python 3.4 or higher 得到 google.appengine
的支持。该错误与函数运行时 google-api-python-client
未作为依赖项安装有关。
尝试将其添加到 Clound 函数编辑器页面上的 requeriments.txt。
您也可以通过import google.auth
使用google-auth
JWT 和访问令牌是两个独立的东西。 JWT由header、声明集和签名三部分组成。另一方面,访问令牌只能从授权服务器获得。请 'Addendum' 部分 this google 文档。我通过传递服务帐户详细信息以编码到 JWT(具有 header 和有效负载)来创建云函数。
signed_jwt = jwt.encode(payload, key, headers=additional_headers, algorithm='RS256')
decoded_signed_jwt = signed_jwt.decode("utf-8")
为了获取访问令牌,请参考以下代码片段。
token_endpoint = 'https://www.googleapis.com/oauth2/v4/token'
token_req_data = {
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion': decoded_signed_jwt
}
token_post_data = urllib.parse.urlencode(token_req_data).encode("utf-8")
access_token_req = urllib.request.Request(token_endpoint, token_post_data)
access_token_req.add_header('Content-Type', 'application/x-www-form-urlencoded')
result = urllib.request.urlopen(access_token_req)
json_str = result.read()
此 json 字符串应包含访问令牌。在要求 API 的请求 header 中使用此访问令牌。请按以下方式更新已签名 JWT 的负载,否则您可能无法获得有效的 JWT。
'scope': 'https://www.googleapis.com/auth/cloud-platform',
'aud': 'https://www.googleapis.com/oauth2/v4/token'
希望这对您有所帮助,感谢 Google 对此答案的某些部分的支持。
我们正在偏离数据存储 scheduled export mechanism (google suggested) and adopting to schedule datastore backup via cloud scheduler which will target HTTP cloud function。在这里,我们想使用云功能将我们的数据存储实体导出到某个存储桶。这种偏离标准机制的原因是,我们希望在所有服务中避免重复的非应用程序特定代码。
根据 docs,托管导出和导入服务只能通过数据存储模式管理 API(REST、RPC)使用,并且请求需要 OAuth 2.0 授权。
在云函数中,要访问数据存储 API https://datastore.googleapis.com/v1/projects/<APP ID>:export
,我们需要范围 https://www.googleapis.com/auth/datastore
.
access_token
在标准的 GAE 应用程序代码中,使用 python27 运行时,我们可以按照下面的示例获得 access_token -
from google.appengine import app_identity
access_token, _ = app_identity.get_access_token('https://www.googleapis.com/auth/datastore')
但是,云函数有 Python37 运行时。因此,导入 google.appengine
给出错误 error as error: ModuleNotFoundError: No module named 'google.appengine'
我们如何获得所需范围的 access_token
? (以下范围之一)-
建议参考Python code/document。谢谢。
Python 3.4 or higher 得到 google.appengine
的支持。该错误与函数运行时 google-api-python-client
未作为依赖项安装有关。
尝试将其添加到 Clound 函数编辑器页面上的 requeriments.txt。
您也可以通过import google.auth
JWT 和访问令牌是两个独立的东西。 JWT由header、声明集和签名三部分组成。另一方面,访问令牌只能从授权服务器获得。请 'Addendum' 部分 this google 文档。我通过传递服务帐户详细信息以编码到 JWT(具有 header 和有效负载)来创建云函数。
signed_jwt = jwt.encode(payload, key, headers=additional_headers, algorithm='RS256')
decoded_signed_jwt = signed_jwt.decode("utf-8")
为了获取访问令牌,请参考以下代码片段。
token_endpoint = 'https://www.googleapis.com/oauth2/v4/token'
token_req_data = {
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion': decoded_signed_jwt
}
token_post_data = urllib.parse.urlencode(token_req_data).encode("utf-8")
access_token_req = urllib.request.Request(token_endpoint, token_post_data)
access_token_req.add_header('Content-Type', 'application/x-www-form-urlencoded')
result = urllib.request.urlopen(access_token_req)
json_str = result.read()
此 json 字符串应包含访问令牌。在要求 API 的请求 header 中使用此访问令牌。请按以下方式更新已签名 JWT 的负载,否则您可能无法获得有效的 JWT。
'scope': 'https://www.googleapis.com/auth/cloud-platform',
'aud': 'https://www.googleapis.com/oauth2/v4/token'
希望这对您有所帮助,感谢 Google 对此答案的某些部分的支持。