REST请求到App Store Connect API的响应为“ 401” | 'NOT_AUTHORIZED'

时间:2018-12-21 14:09:34

标签: python ios jwt

我们启动了一个iOS-App,我想从App Store Connect API中获取一些信息(例如,安装,更新,评论)。

我按照Apple官方文档Link

中的描述创建JSON Web令牌。

然后,我用标头中的令牌发出请求。现在我得到一个“ 401” |每次将“ NOT_AUTHORIZED”作为答案,请参见下图: REST Response

在以下代码片段中,您可以看到我的python代码(我试图在Python和R中解决它,但结果始终相同)。

首先,我创建一个JWT:


    from datetime import datetime, timedelta
    from jose import jwt, jws
    import ecdsa

    KEY_ID = "XXXXXXXXXX"
    ISSUER_ID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    PRIVATE_KEY = open('AuthKey_XXXXXXXXXX.p8', 'r').read()
    TIMESTAMP = int( (datetime.now() - timedelta(minutes = 45)).timestamp() * 1000)

    claim = {"iss" : ISSUER_ID,
             "exp" : TIMESTAMP,
             "aud" : "appstoreconnect-v1"}

    header = {
             "alg": "ES256",
             "kid": KEY_ID,
             "typ": "JWT"
             }

    # Create the JWT
    encoded = jwt.encode(claim, PRIVATE_KEY, algorithm='ES256', headers=header)

现在,当我打印编码的时,我将遵循以下JWT(对我来说看起来很有效):


'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IlhYWFhYWFhYWFgifQ.eyJpc3MiOiJYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFgiLCJleHAiOjE1NDUzOTc1MTQ1ODAsImF1ZCI6ImFwcHN0b3JlY29ubmVjdC12MSJ9.eTl6iaAW-Gp67FNmITrWCpLTtJzVdLYXIl5_KKgqaNgzwyGo7npBOBo9_u5PtLNnssQFEwJWbPND-6Ww5ACgEg'

即使我通过Base64解码了JWT的前两个部分,我也得到了正确的 Header (它还包含正确的编码算法:'alg':'ES256')和索赔


    from jose.utils import base64url_decode
    print(base64url_decode(b'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IlhYWFhYWFhYWFgifQ'))
    print(base64url_decode(b'eyJpc3MiOiJYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFgiLCJleHAiOjE1NDUzOTc1MTQ1ODAsImF1ZCI6ImFwcHN0b3JlY29ubmVjdC12MSJ9'))

请参见下图:Output Base64 Decoding

现在,我认为JWT对象已经准备好了,我将请求发送到API:


    import requests

    JWT = 'Bearer ' + encoded

    URL = 'https://api.appstoreconnect.apple.com/v1/apps'
    HEAD = {'Authorization': JWT} 
    print(HEAD)

    R = requests.get(URL, headers=HEAD)
    R.json()

现在我们可以看到我的问题,请参见图片:Header | REST Response

请注意,对于示例,我已经隐藏了 KEY_ID ISSUER_ID PRIVATE_KEY

3 个答案:

答案 0 :(得分:0)

您的令牌包含有效时间

  

“ exp”:1545397514580,

等于50941年9月12日。

当我删除最后三位数字

  

“ exp”:1545397514,

我到了2018年12月21日 这更有意义。

更改该行

TIMESTAMP = int( (datetime.now() - timedelta(minutes = 45)).timestamp() * 1000)

TIMESTAMP = int( (datetime.now() - timedelta(minutes = 45)).timestamp())

exp是一个时间戳,定义为自1970年1月1日00:00以来的秒数。 另请参见here

答案 1 :(得分:0)

首先,请不要在没有上下文管理器的情况下打开文件。该字符串:

PRIVATE_KEY = open('AuthKey_XXXXXXXXXX.p8', 'r').read()

应为:

with open('AuthKey_XXXXXXXXXX.p8', 'r') as f:
    PRIVATE_KEY = f.read()

它将使您免于以后遇到未关闭文件的许多麻烦。

然后,检查您从文件中读取了什么令牌。正确吗?

我看到的下一个问题是时间戳。 “令牌的到期时间,以Unix纪元时间为单位;”我猜您以毫秒为单位提供它。

答案 2 :(得分:0)

这是对我有用的解决方案。立即返回 401 错误

KEY_ID = "xxxxx"
ISSUER_ID = "xxxxx"
EXPIRATION_TIME = int(round(time.time() + (20.0 * 60.0))) # 20 minutes timestamp
PATH_TO_KEY = '../credentials/AuthKey_xxxxx.p8'
with open(PATH_TO_KEY, 'r') as f:
    PRIVATE_KEY = f.read()

header = {
    "alg": "ES256",
    "kid": KEY_ID,
    "typ": "JWT"
}

payload = {
    "iss": ISSUER_ID,
    "exp": EXPIRATION_TIME,
    "aud": "appstoreconnect-v1"
}

# Create the JWT
token = jwt.encode(header, payload, PRIVATE_KEY)
JWT = 'Bearer ' + token.decode()
HEAD = {'Authorization': JWT}

# Without delay I got 401 error
time.sleep(5)

URL = 'https://api.appstoreconnect.apple.com/v1/apps';
r = requests.get(URL, params={'limit': 200}, headers=HEAD)