【发布时间】:2019-10-30 08:11:58
【问题描述】:
我正在尝试使用 PHP 使用 ES256 签名的 JWT(根据他们在 https://developer.apple.com/documentation/appstoreconnectapi 的说明)对 Apple 的 AppStoreConnect API 进行身份验证。
发送我的请求总是会导致 401 NOT_AUTHORIZED 错误。
我已经验证我的标题和声明的内容是正确的 - 我什至在网上找到了一个 Ruby 脚本,用于生成一个 ES256 签名的 JWT 并使用我的 Apple 提供的颁发者、密钥 ID、私钥,它可以正常工作 - Apple接受令牌。这告诉我我的凭据很好,我在 php 中做错了。
除非我只是盯着这段代码太久,否则 JWT 格式正确,base64 编码正确,并且在 header 中正确设置了不记名令牌。
为了排除请求发送的问题,我尝试了 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;
}
此代码成功返回一个打开的 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;
}
Base64 URL 编码...$data 具有预期的内容。
public function encode($data)
{
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
}
在这一点上,我很困惑我做错了什么或错过了什么。我希望一些额外的眼睛会发现一些东西!使用我的代码转储出来的令牌:
curl https://api.appstoreconnect.apple.com/v1/users --Header "Authorization: Bearer <token>”
...总是返回401。我怀疑代码的签名部分有问题,因为这是我唯一无法验证的部分(再次,在 Ruby 中工作),尽管查看了openssl_sign 的所有文档和示例,我很漂亮确定是对的。
作为参考,这是我提到的 Ruby 脚本https://shashikantjagtap.net/generating-jwt-tokens-for-app-store-connect-api/
【问题讨论】:
标签: php jwt sha256 ecdsa app-store-connect