【问题标题】:Gsuite Directory API 403 Error on API call or Grant Type Error on JWT GenerationGsuite Directory API 403 API 调用错误或 JWT 生成授予类型错误
【发布时间】: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


    【解决方案1】:

    documentation 有一个清晰的概述,您是否按照附录中描述的步骤进行操作?我遗漏了您的代码的某些部分。但是您没有提到使用服务帐户(json)密钥。并且文档还显示您必须将(委托)服务帐户同时用作 iss 和 sub。此外,你需要使用一个孩子。它是这样完成的:

    payload = {
        'iss': '123456-compute@developer.gserviceaccount.com',
        'sub': '123456-compute@developer.gserviceaccount.com',
        'aud': 'https://firestore.googleapis.com/',
        'iat': time.time(),
        'exp': iat + 3600
    }
    additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
    signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers, algorithm='RS256')
    
    url = "URL OF THE API TO CALL"
    header = {'Authorization': f'Bearer {signed_jwt}'}
    resp = requests.get(url, headers=header)
    

    注意:您可以在服务帐户 JSON 凭据文件的 private_key_id 字段中找到 PRIVATE_KEY_FROM_JSON

    【讨论】:

    • 我必须验证是否可以仅通过 JWT 访问 Directory API / AdminSDK。我将编辑我的原始帖子以包含我为处理 JWT 而创建的函数调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多