ES256 JWT Signing in PHP for Apple AppStoreConenct API Auth

∥☆過路亽.° 提交于 2019-12-08 04:34:17

问题


I'm trying to authenticate to Apple's AppStoreConnect API with an ES256 signed JWT (per their instructions at https://developer.apple.com/documentation/appstoreconnectapi) using PHP.

Sending my request always results in a 401 NOT_AUTHORIZED error.

I've verified that the the contents of my header and claims are correct - I even found a Ruby script online for generating an ES256 signed JWT and using my Apple provided Issuer, Key ID, Private Key, it works swimmingly - Apple accepts the token. That tells me that my credentials are good and I'm doing something wrong in php.

Unless I've simply stared at this code for too long, the JWT format is correct, base64 encoded correctly, and the bearer token is set correctly in the header.

To rule out an issue with request sending I've tried both GuzzleHTTP and CLI cURL - both a 401.


Here's the relevant code. You'll see that the create method is encoding the header and claims, signing the "payload", and concatenating all 3.

public function create()
{
    $header = $this->encode(
        json_encode([
            'kid' => 'my_key_id',
            'alg' => 'ES256',
            'typ' => 'JWT',
        ])
    );

    $claims = $this->encode(
        json_encode([
            'iss' => 'my_issuer_uuid',
            'exp' => time() + (20 * 60),
            'aud' => 'appstoreconnect-v1',
        ])
    );

    $signature = $this->encode(
        $this->sign("$header.$claims")
    );

    return $header . '.' . $claims . '.' . $signature;
}

This code successfully returns an open ssl resource, $data has the expected contents.

public function sign($data)
{
    if (!$key = openssl_pkey_get_private('file://my_key_file.p8')) {
        throw new \Exception('Failed to read PEM');
    }

    if (!openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA256)) {
        throw new \Exception('Claims signing failed');
    }

    return $signature;
}

Base64 URL encoding... $data has the expected contents.

public function encode($data)
{
    return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
}

At this point I'm stumped to what it is I'm doing wrong or missing. I'm hoping some extra eyes will find something! Using the token that my code dumps out:

curl  https://api.appstoreconnect.apple.com/v1/users --Header "Authorization: Bearer <token>”

...always returns a 401. I suspect there's something wrong in the signing portion of the code as it's the only part I haven't been able to verify (again, worked in Ruby), though looking at all the docs and examples for openssl_sign, I'm pretty sure it's right.

For reference, this is the Ruby script I mention https://shashikantjagtap.net/generating-jwt-tokens-for-app-store-connect-api/


回答1:


The signature returned by OpenSSL is an ASN.1 sequence that contains additional information. You have to remove the extra data before concatenation.

You can use that simple class I wrote (method fromDER) to convert the OpenSSL signature.




回答2:


After struggling alot, i finally got it working using https://github.com/lcobucci/jwt

use Curl\Curl;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;

$signer = new Sha256();
$privateKey = new Key('file://AuthKey_XYZ.p8');
$time = time();

$Issuer_ID = "FROM_APPLE_PAGE";
$Key_ID = "FROM_APPLE_PAGE";

$token = (new Builder())->issuedBy($Issuer_ID)// Configures the issuer (iss claim)
->permittedFor("appstoreconnect-v1")// Configures the audience (aud claim)
->identifiedBy('XXYYZZ', true)// Configures the id (jti claim), replicating as a header item
->withHeader('kid', $Key_ID)
->withHeader('type', 'JWT')
    ->withHeader('alg', 'ES256')
    ->issuedAt($time)// Configures the time that the token was issue (iat claim)
    ->expiresAt($time + 1200)// Configures the expiration time of the token (exp claim)
    ->withClaim('uid', 1)// Configures a new claim, called "uid"
    ->getToken($signer, $privateKey); // Retrieves the generated token


$token->getHeaders(); // Retrieves the token headers
$token->getClaims(); // Retrieves the token claims


来源:https://stackoverflow.com/questions/56619355/es256-jwt-signing-in-php-for-apple-appstoreconenct-api-auth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!