Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Generate ES256 JWT tokens for Apple Push Notification Service (APNS) in PHP
<?php
function base64url_encode($binary_data) { return strtr(rtrim(base64_encode($binary_data), '='), '+/', '-_'); }
function apns_jwt_token($team_id, $key_id, $private_key_pem_str)
{
if (! function_exists('openssl_get_md_methods') || ! in_array('sha256', openssl_get_md_methods())) throw new Exception('Requires openssl with sha256 support');
$private_key = openssl_pkey_get_private($private_key_pem_str);
if (! $private_key) throw new Exception('Cannot decode private key');
$msg = base64url_encode(json_encode([ 'alg' => 'ES256', 'kid' => $key_id ])) . '.' . base64url_encode(json_encode([ 'iss' => $team_id, 'iat' => time() ]));
openssl_sign($msg, $der, $private_key, 'sha256');
// DER unpacking from https://github.com/firebase/php-jwt
$components = [];
$pos = 0;
$size = strlen($der);
while ($pos < $size) {
$constructed = (ord($der[$pos]) >> 5) & 0x01;
$type = ord($der[$pos++]) & 0x1f;
$len = ord($der[$pos++]);
if ($len & 0x80) {
$n = $len & 0x1f;
$len = 0;
while ($n-- && $pos < $size) $len = ($len << 8) | ord($der[$pos++]);
}
if ($type == 0x03) {
$pos++;
$components[] = substr($der, $pos, $len - 1);
$pos += $len - 1;
} else if (! $constructed) {
$components[] = substr($der, $pos, $len);
$pos += $len;
}
}
foreach ($components as &$c) $c = str_pad(ltrim($c, "\x00"), 32, "\x00", STR_PAD_LEFT);
return $msg . '.' . base64url_encode(implode('', $components));
}
@komaxx
Copy link

komaxx commented Apr 21, 2020

Neat, thank you!
Needs a few more class hierarchies, though ;)

@hassaan-dev
Copy link

hassaan-dev commented Jun 1, 2021

Thank you for this great share

@justingreerbbi
Copy link

justingreerbbi commented Aug 30, 2021

Awesome work. Simple and not over complicated like most packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment