'I want to get data from API provided by Apple and I can't generate jwt token?
There is an API provided by Apple and I want to generate jwt tokens to use it. I will explain step by step what I did.
$pem_content = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
Private key provided by Apple
-----END RSA PRIVATE KEY-----
EOD;
$header = json_encode(array(
'alg' => 'ES256',
'kid' => 'Keyid given by Apple',
'typ' => 'JWT'
));
$payload = json_encode(array(
'iss' => ' issuer ID given by Apple',
'iat' => 1623085200,
'exp' => 1623086400,
'aud' => 'appstoreconnect-v1',
'bid' => 'My app’s bundle ID'
));
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
There is no problem in the above part, when I print it with dd(), token is generated and when I try it on jwt.io site, header and payload parts come
$signature = '';
openssl_sign($base64UrlHeader . "." . $base64UrlPayload, $signature, openssl_get_privatekey($pem_content), OPENSSL_ALGO_SHA1);
When I print this part with dd() it returns true.
$signature = $this->FromDER($signature, 64);
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
$jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
This is where the problem starts. What I learned is to convert the DER encoded signature to a raw combination of R and S values. In this library a function "fromDER" is present which perform such a conversion:
/**
* @param string $der
* @param int $partLength
*
* @return string
*/
public static function fromDER(string $der, int $partLength)
{
$hex = unpack('H*', $der)[1];
if ('30' !== mb_substr($hex, 0, 2, '8bit')) { // SEQUENCE
throw new \RuntimeException();
}
if ('81' === mb_substr($hex, 2, 2, '8bit')) { // LENGTH > 128
$hex = mb_substr($hex, 6, null, '8bit');
} else {
$hex = mb_substr($hex, 4, null, '8bit');
}
if ('02' !== mb_substr($hex, 0, 2, '8bit')) { // INTEGER
throw new \RuntimeException();
}
$Rl = hexdec(mb_substr($hex, 2, 2, '8bit'));
$R = self::retrievePositiveInteger(mb_substr($hex, 4, $Rl * 2, '8bit'));
$R = str_pad($R, $partLength, '0', STR_PAD_LEFT);
$hex = mb_substr($hex, 4 + $Rl * 2, null, '8bit');
if ('02' !== mb_substr($hex, 0, 2, '8bit')) { // INTEGER
throw new \RuntimeException();
}
$Sl = hexdec(mb_substr($hex, 2, 2, '8bit'));
$S = self::retrievePositiveInteger(mb_substr($hex, 4, $Sl * 2, '8bit'));
$S = str_pad($S, $partLength, '0', STR_PAD_LEFT);
return pack('H*', $R.$S);
}
/**
* @param string $data
*
* @return string
*/
private static function preparePositiveInteger(string $data)
{
if (mb_substr($data, 0, 2, '8bit') > '7f') {
return '00'.$data;
}
while ('00' === mb_substr($data, 0, 2, '8bit') && mb_substr($data, 2, 2, '8bit') <= '7f') {
$data = mb_substr($data, 2, null, '8bit');
}
return $data;
}
/**
* @param string $data
*
* @return string
*/
private static function retrievePositiveInteger(string $data)
{
while ('00' === mb_substr($data, 0, 2, '8bit') && mb_substr($data, 2, 2, '8bit') > '7f') {
$data = mb_substr($data, 2, null, '8bit');
}
return $data;
}
But when I include it, I get RuntimeException. Where am I going wrong while generating tokens?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
