用于 Apple AppStoreConenct API Auth 的 ES256 JWT 登录 PHP

Chr*_*gue 6 php sha256 jwt ecdsa app-store-connect

我正在尝试使用 PHP通过 ES256 签名的 JWT(根据他们在https://developer.apple.com/documentation/appstoreconnectapi 上的说明)对 Apple 的 AppStoreConnect API 进行身份验证。

发送我的请求总是会导致401 NOT_AUTHORIZED错误。

我已经验证了我的标题和声明的内容是正确的 - 我什至在网上找到了一个 Ruby 脚本来生成一个 ES256 签名的 JWT 并使用我的 Apple 提供的颁发者、密钥 ID、私钥,它运行良好 - Apple 接受令牌. 这告诉我我的凭据很好,但我在 php 中做错了。

除非我只是盯着这段代码看太久,否则 JWT 格式是正确的,base64 编码正确,并且不记名令牌在标头中设置正确。

为了排除请求发送的问题,我尝试了 GuzzleHTTP 和 CLI cURL - 都是 401。


这是相关的代码。您将看到该create方法正在对标头和声明进行编码、签署“有效负载”并连接所有 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;
}
Run Code Online (Sandbox Code Playgroud)

此代码成功返回一个打开的 ssl 资源,$data具有预期的内容。

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;
}
Run Code Online (Sandbox Code Playgroud)

Base64 URL 编码...$data具有预期的内容。

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

在这一点上,我很难过我做错了什么或错过了什么。我希望一些额外的眼睛会发现一些东西!使用我的代码转储出来的令牌:

curl  https://api.appstoreconnect.apple.com/v1/users --Header "Authorization: Bearer <token>”
Run Code Online (Sandbox Code Playgroud)

...总是返回一个401. 我怀疑代码的签名部分有问题,因为它是我唯一无法验证的部分(同样,在 Ruby 中工作),尽管查看了 的所有文档和示例openssl_sign,但我很确定它是正确的.

作为参考,这是我提到的 Ruby 脚本https://shashikantjagtap.net/generating-jwt-tokens-for-app-store-connect-api/

Flo*_*lli 0

OpenSSL 返回的签名是包含附加信息的 ASN.1 序列。您必须在串联之前删除多余的数据。

您可以使用我编写的简单类(方法fromDER)来转换 OpenSSL 签名。