Я пытаюсь пройти аутентификацию в Apple AppStoreConnect API с подписанным ES256 JWT (согласно их инструкциям на https://developer.apple.com/documentation/appstoreconnectapi) с использованием PHP.
Отправка моего запроса всегда приводит к ошибке 401 NOT_AUTHORIZED
.
Я убедился, что содержимое моего заголовка и утверждений правильное - я даже нашел в Интернете скрипт Ruby для генерации JWT с подписью ES256 и использования предоставленного Apple эмитента, идентификатора ключа, секретного ключа, он работаетплавно - 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;
}
Этот код успешно возвращает открытый ресурс 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/