【发布时间】:2020-06-18 22:56:45
【问题描述】:
使用 Python 并使用 HTTP/Rest 方法创建我自己的 JWT,我根本无法让委托工作。
一方面,谷歌 JWT 故障排除文档说 ISS 需要与 SUB(服务帐户)相同。
但是,在服务器到服务器的 oauth2 文档中,它说要模拟一个帐户,sub 必须是我在声明中尝试模拟的帐户。
不用说,尽管启用了域范围的委派、添加了正确的范围等,但在尝试使用 python 中的 requests 库访问用户域时,除了 403 之外,我什么也没得到,下面的示例:
> requests.get("https://www.googleapis.com/admin/directory/v1/users/useremail@/
> google.org",headers={'Authorization':f' Bearer {oauth2tokenhere}'})
这是我的主张的一个例子:
> claim = { "iss": 'serviceaccountemail',
> 'sub': 'impersonatedaccountemail',
> 'scope': 'https://www.googleapis.com/auth/admin.directory.user.readonly',
> 'exp': ((datetime.datetime.today() + datetime.timedelta(minutes=60)).timestamp()),
> 'iat': ((datetime.datetime.today()).timestamp()),
> 'aud': "https://oauth2.googleapis.com/token"
> }
上述声明将产生一个广义的授权错误(可爱,但没有帮助)。
如果我更改声明并确保 sub 和 iss 相同,则会生成 oauth2token,但在尝试访问 API 时出现 403 错误。
这是服务器到服务器的 oauth2 文档,说明 sub 应该是 服务帐户试图模拟的帐户。
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
这是概述 ISS/Sub 相同的故障排除文章(尽管云文章是我能找到的最接近的相关主题)
https://cloud.google.com/endpoints/docs/openapi/troubleshoot-jwt
编辑:
我正在使用创建服务帐户文件时下载的已下载 .json 文件中的服务帐户信息。
import json as j
import datetime
import jwt
import requests
#creates the claim, 'secret' (from the private key), and the kid, from the service account file, and returns these values in a tuple.
#the tuple can then be used to make dependable positional argument entries to the parameters of the createJWT function.
def create_claim_from_json(self,objpath,scope=["https://www.googleapis.com/auth/admin.directory.user.readonly" "https://www.googleapis.com/auth/admin.directory.user"]):
with open(f'{objpath}','r') as jobj:
data = j.load(jobj)
claim = {
"iss": str(data['client_id']),
"sub": str(data['client_id']),
"scope": str(scope),
"exp": ((datetime.datetime.today() + datetime.timedelta(minutes=59)).timestamp()),
"iat": ((datetime.datetime.today()).timestamp()),
"aud": "https://oauth2.googleapis.com/token"
}
private_key = data['private_key']
kid = {"kid": f"{data['private_key_id']}"}
return claim, private_key, kid
#assembles the JWT using the claim, secret (Private key from the Service account file), the kid value, and the documented RS256 alg.
#returns the completed JWT object back to be used to send to the oauth2 endpoint
#the JWT will be used in the function call retrieve_oauth2token.
def createJWT(self, claim, secret, kid, alg='RS256'):
encoded_jwt = (jwt.encode(claim, secret, alg, kid)).decode('UTF-8')
return encoded_jwt
#Using the JWT created in memory, sends the JWT to the googleapi oauth2 uri and returns a token
def retrieve_oauth2token(self, jwt):
oauth2 = requests.post(f'https://oauth2.googleapis.com/token?grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant- type%3Ajwt-bearer&assertion={jwt}')
oauth2=oauth2.json()
return oauth2 #['access_token'], oauth2['token_type']
【问题讨论】:
标签: jwt google-workspace