用于 Apple AppStoreConenct API Auth 的 ES256 JWT 登录 PHP [英] ES256 JWT Signing in PHP for Apple AppStoreConenct API Auth

查看:97
本文介绍了用于 Apple AppStoreConenct API Auth 的 ES256 JWT 登录 PHP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

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

Sending my request always results in a 401 NOT_AUTHORIZED error.

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

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.

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

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.

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

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

这是相关的代码.您将看到 create 方法正在对标头和声明进行编码,签署有效负载",并连接所有 3 个.

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;
}

这段代码成功返回了一个打开的ssl资源,$data有预期的内容.

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 编码... $data 有预期的内容.

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>"

...总是返回 401.我怀疑代码的签名部分有问题,因为这是我唯一无法验证的部分(再次使用 Ruby),尽管查看了 openssl_sign 的所有文档和示例,我很确定这是对的.

...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.

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

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

推荐答案

经过大量测试,这里对我有用:

After a lot of testing here is what worked for me:

安装这个包:

composer require lcobucci/jwt

立即尝试生成令牌:

<?php

require 'vendor/autoload.php';

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

$signer = new Sha256();
$key = file_get_contents('AuthKey_xxxx.p8');

$privateKey = new Key($key);
$time = time();

$token = (new Builder())->issuedBy('AppleTeamID') // Configures the issuer (iss claim)
    ->withHeader('alg', 'ES256')
    ->withHeader('kid', 'AppleKeyID')
    ->issuedAt($time) // Configures the time that the token was issue (iat claim)
    ->expiresAt($time + 1200) // Configures the expiration time of the token (exp claim)
    ->getToken($signer, $privateKey); // Retrieves the generated token

// Test if your key works OK
exec("curl -v -H 'Authorization: Bearer {$token}' \"https://api.music.apple.com/v1/catalog/us/artists/36954\"");


exit;

这篇关于用于 Apple AppStoreConenct API Auth 的 ES256 JWT 登录 PHP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆