Search code examples
phpjwtapp-store-connectguzzle

AppStore connect API 401 ERROR, while using Firebase\JWT


I am trying to get reports and data from AppleStore connect API, but it keeps giving me 401 ERROR.

{ "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" }] }

I was using the guidelines from here => generating_tokens_for_api_requests and using firebase/php-jwt library to create jwt token for the Auth. In the App store connect, the key has Developer access privileges.

My sample code for it as follows:

date_default_timezone_set("Europe/Madrid");
use \Firebase\JWT\JWT;

$appleCon = [
    'privateKey' => "" . file_get_contents(__DIR__ . '/AuthKey_XXXXXXXXX.p8'),
    'apiKeyID' => 'XXXXXXXXX',
    'issuerID' => 'XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX'
];

$payload = array(
    "iss" => $appleCon['issuerID'],
    "exp" => time() + 1200,
    "aud" => "appstoreconnect-v1",
);

$jwt = JWT::encode($payload, $appleCon['privateKey'], "ES256", $appleCon['apiKeyID']);

$client = new GuzzleHttp\Client(['base_uri' => 'https://api.appstoreconnect.apple.com/v1/']);
$request = new \GuzzleHttp\Psr7\Request('GET', 'apps', [
    'headers' => [
        'Authorization' => "Bearer ".$jwt
    ]
]);

$promise = $client->sendAsync($request)->then(function ($response) {
    echo 'I completed! ' . $response->getBody();
});

try {
    $promise->wait();
}
catch (GuzzleHttp\Exception\ClientException $e) {
    $response = $e->getResponse();
    $responseBodyAsString = $response->getBody()->getContents();

    echo $responseBodyAsString;
}

Content of the AuthKey_XXXXXXXXX.p8 file as follows:

-----BEGIN PRIVATE KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END PRIVATE KEY-----

I am struggling with this issue for two days, if anyone can fix or give some hints to fix this issue, will be much appreciated.


Solution

  • It was a problem with guzzle. when I used it without async. it started to work

    $response = $client->request('GET', 'apps', ['headers' => ['Authorization' => "Bearer $jwt"]])->getBody()->getContents();
    

    If anyone can provide me a reason, why it happens when I use it asynchrony, would be interesting to learn it.