fork download
  1. <?php declare(strict_types=1);
  2.  
  3. /* URL-safe Base64 encode and decode, as PHP does not natively have this function */
  4. function base64_urlencode($subject): string
  5. {
  6. return strtr(rtrim(base64_encode($subject), '='), '+/', '-_');
  7. }
  8.  
  9. function base64_urldecode($subject): string
  10. {
  11. return base64_decode(strtr($subject, '-_', '+/'));
  12. }
  13.  
  14. function jwt_encode(string $secret, array $header, array $payload) : string
  15. {
  16. $header_code = base64_urlencode(json_encode($header));
  17. $payload_code = base64_urlencode(json_encode($payload));
  18.  
  19. $token = vsprintf('%s.%s', [
  20. $header_code,
  21. $payload_code,
  22. ]);
  23.  
  24. $signature = hash_hmac('sha256', $token, $secret);
  25.  
  26. $signature_code = base64_urlencode($signature);
  27.  
  28. return vsprintf('%s.%s.%s', [
  29. $header_code,
  30. $payload_code,
  31. $signature,
  32. ]
  33. );
  34. }
  35.  
  36. function jwt_decode(string $secret, string $jwt) : array
  37. {
  38. [$header_code, $payload_code, $signature] = explode('.', $jwt);
  39.  
  40. $header = json_decode(base64_urldecode($header_code), true);
  41. $payload = json_decode(base64_urldecode($payload_code), true);
  42.  
  43. $availableAlgorithms = ['HS256' => 'sha256'];
  44. $algorithm = $availableAlgorithms[$header['alg']];
  45.  
  46. $token = vsprintf('%s.%s', [
  47. $header_code,
  48. $payload_code,
  49. ]);
  50.  
  51. $jwt_signature = hash_hmac($algorithm, $token, $secret);
  52.  
  53. if ($jwt_signature !== $signature) {
  54. throw new \UnexpectedValueException('Signature verification failed!');
  55. }
  56.  
  57. return $payload;
  58. }
  59.  
  60. $header = ['typ' => 'JWT', 'alg' => 'HS256'];
  61.  
  62. $payload = [
  63. 'This is' => 'some data'
  64. ];
  65.  
  66. $secret = 'My S3cR3t!';
  67.  
  68. $jwt = jwt_encode($secret, $header, $payload);
  69.  
  70. $jwt_payload = jwt_decode($secret, $jwt);
  71.  
  72. var_dump($jwt, $jwt_payload === $payload, $payload);
  73.  
Success #stdin #stdout 0.04s 24224KB
stdin
Standard input is empty
stdout
string(133) "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJUaGlzIGlzIjoic29tZSBkYXRhIn0.d885e9952da69fad379d3d6f9fe6b021f45b608d9811682ee0f77b7c3eaa71fd"
bool(true)
array(1) {
  ["This is"]=>
  string(9) "some data"
}