Skip to content

Instantly share code, notes, and snippets.

@marcoarment
Last active April 14, 2024 06:49
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save marcoarment/1d84a2619b3bc1a8216e443c9a0fa269 to your computer and use it in GitHub Desktop.
Save marcoarment/1d84a2619b3bc1a8216e443c9a0fa269 to your computer and use it in GitHub Desktop.
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

Thank you for this great share

@justingreerbbi
Copy link

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

@DrBrad
Copy link

DrBrad commented Nov 18, 2023

Bro I spent 3 days trying to figure out why my JWT generation wasnt working and
// DER unpacking from https://github.com/firebase/php-jwt and below got it working bro thank you xD

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