victorxu2
victorxu2

Reputation: 514

Authentication credentials are missing or invalid app store connect api python

I am trying to use sales report API from App Store Connect API with Python script here.

import jwt
import requests
import time
import json

KEY_ID = "XXXXXXXXX"
ISSUER_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# EXPIRATION_TIME = int(round(time.time() + (20.0 * 60.0))) # 20 minutes timestamp
PATH_TO_KEY = '/Users/164187.victor/Documents/Credentials/App_Store_Connect_RR/AuthKey_XXXXXXXXX.p8'
# pseudo, removed secret info
# read the file, currently binary but have tried string too
with open(PATH_TO_KEY, 'r+b') as keyfile:
    secret = keyfile.read()
expir = round(time.time() + 20 * 60)
# sign the token with the iss, time, key, and kid with the correct alg
token = jwt.encode({'iss': ISSUER_ID, 
                    'exp': expir, 
                    'aud': 'appstoreconnect-v1'},
                    secret, algorithm='ES256', 
                    headers={'alg': 'ES256', 'kid': KEY_ID, 'typ': 'JWT'})

# decode the bytes and create the get request header
headers = {'Authorization': f'Bearer {token}'}

params = {'filter[reportSubType]': 'SUMMARY', 'filter[reportType]': 'SALES', 'filter[frequency]':'DAILY', 'filter[vendorNumber]': 'XXXXXXXX'}
# send the get request
r = requests.get('https://api.appstoreconnect.apple.com/v1/salesReports',
                 headers=headers, params=params)

# Write the response in a pretty printed JSON file
with open('output.json', 'w') as out:
    out.write(json.dumps(r.json(), indent=4))

and i got this result in my json output file:

{
    "errors": [
        {
            "status": "401",
            "code": "NOT_AUTHORIZED",
            "title": "Authentication credentials are missing or invalid.",
            "detail": "Provide a properly configured and signed bearer token, and make sure that it has not expired. Learn more about Generating Tokens for API Requests https://developer.apple.com/go/?id=api-generating-tokens"
        }
    ]
}

What i have tried:

  1. checking my token in jwt.io, and it does works fine there.
  2. using admin access level for key privilege
  3. trying to remove 'alg' properties in headers cause some post said it will solve the problem but it doesnt work for me

is there anything to solve this problem? i already stuck at this for 1 week pls help

Upvotes: 1

Views: 6912

Answers (2)

Yang.Y
Yang.Y

Reputation: 2238

It seemed your code originates from this Gist, it uses authlib to create JWT token. But import jwt statement in your code indicates you have switched to PyJWT, don't mix up two packages, they have different ways to use.

For PyJWT:

import jwt

token_data = jwt.encode(
    {
        'iss': ISSUER_ID,
        'aud': 'appstoreconnect-v1',
        'exp': expiry
    },
    secret,
    headers={
        'kid': KEY_ID
    },
    algorithm='ES256'
)

print(token_data.decode('UTF-8'))

For authlib:

from authlib.jose import jwt

token_data = jwt.encode(
    {
        "alg": "ES256",
        "kid": KEY_ID,
        "typ": "JWT"
    },
    {
        "iss": ISSUER_ID,
        "exp": expir,
        "aud": "appstoreconnect-v1"
    },
    secret
)

print(token.decode())

For both ways, don't forget invoke decode() before being used in request headers.

Another better option would be using applaud – a Python client library for accessing App Store Connect API, you simply pass the credentials to initialize a Connection object, applaud does the rest for you:

# Create the Connection
connection = Connection(ISSUER_ID, KEY_ID, PRIVATE_KEY)

r = connection.sales_reports().filter(
    report_sub_type=SalesReportsEndpoint.ReportSubType.SUMMARY, # or "SUMMARY"
    report_type=SalesReportsEndpoint.ReportType.SALES, # or "SALES"
    frequency=SalesReportsEndpoint.Frequency.MONTHLY, # or "MONTHLY"
    report_date='2021-12',
    vendor_number='12345678',
).get()

r.save('output.txt', decompress=True)

You can find your vendor number in Payments and Financial Reports. Example code is here.

Full disclosure, I'm original author of applaud.

Upvotes: 0

Lukas Marschall
Lukas Marschall

Reputation: 93

Given the link in your error, https://developer.apple.com/go/?id=api-generating-tokens, you are missing the iat(Issued at Time) and the scope parameters in your payload.

Upvotes: 0

Related Questions