File indexing completed on 2024-12-22 05:37:18
0001 <?php 0002 0003 /** 0004 * JSON Web Token implementation, based on this spec: 0005 * http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06 0006 * 0007 * PHP version 5 0008 * 0009 * @category Authentication 0010 * @package Authentication_JWT 0011 * @author Neuman Vong <neuman@twilio.com> 0012 * @author Anant Narayanan <anant@php.net> 0013 * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD 0014 * @link https://github.com/firebase/php-jwt 0015 */ 0016 class JWT 0017 { 0018 /** 0019 * Decodes a JWT string into a PHP object. 0020 * 0021 * @param string $jwt The JWT 0022 * @param string|null $key The secret key 0023 * @param bool $verify Don't skip verification process 0024 * 0025 * @return object The JWT's payload as a PHP object 0026 * @throws UnexpectedValueException Provided JWT was invalid 0027 * @throws DomainException Algorithm was not provided 0028 * 0029 * @uses jsonDecode 0030 * @uses urlsafeB64Decode 0031 */ 0032 public static function decode($jwt, $key = null, $verify = true) 0033 { 0034 $tks = explode('.', $jwt); 0035 if (count($tks) != 3) { 0036 throw new UnexpectedValueException('Wrong number of segments'); 0037 } 0038 list($headb64, $bodyb64, $cryptob64) = $tks; 0039 if (null === ($header = JWT::jsonDecode(JWT::urlsafeB64Decode($headb64)))) { 0040 throw new UnexpectedValueException('Invalid segment encoding'); 0041 } 0042 if (null === $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64))) { 0043 throw new UnexpectedValueException('Invalid segment encoding'); 0044 } 0045 $sig = JWT::urlsafeB64Decode($cryptob64); 0046 if ($verify) { 0047 if (empty($header->alg)) { 0048 throw new DomainException('Empty algorithm'); 0049 } 0050 if ($sig != JWT::sign("$headb64.$bodyb64", $key, $header->alg)) { 0051 throw new UnexpectedValueException('Signature verification failed'); 0052 } 0053 } 0054 0055 return $payload; 0056 } 0057 0058 /** 0059 * Decode a JSON string into a PHP object. 0060 * 0061 * @param string $input JSON string 0062 * 0063 * @return object Object representation of JSON string 0064 * @throws DomainException Provided string was invalid JSON 0065 */ 0066 public static function jsonDecode($input) 0067 { 0068 $obj = json_decode($input); 0069 if (function_exists('json_last_error') && $errno = json_last_error()) { 0070 JWT::_handleJsonError($errno); 0071 } else if ($obj === null && $input !== 'null') { 0072 throw new DomainException('Null result with non-null input'); 0073 } 0074 0075 return $obj; 0076 } 0077 0078 /** 0079 * Helper method to create a JSON error. 0080 * 0081 * @param int $errno An error number from json_last_error() 0082 * 0083 * @return void 0084 */ 0085 private static function _handleJsonError($errno) 0086 { 0087 $messages = array( 0088 JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', 0089 JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', 0090 JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON' 0091 ); 0092 throw new DomainException(isset($messages[$errno]) ? $messages[$errno] : 'Unknown JSON error: ' . $errno); 0093 } 0094 0095 /** 0096 * Decode a string with URL-safe Base64. 0097 * 0098 * @param string $input A Base64 encoded string 0099 * 0100 * @return string A decoded string 0101 */ 0102 public static function urlsafeB64Decode($input) 0103 { 0104 $remainder = strlen($input) % 4; 0105 if ($remainder) { 0106 $padlen = 4 - $remainder; 0107 $input .= str_repeat('=', $padlen); 0108 } 0109 0110 return base64_decode(strtr($input, '-_', '+/')); 0111 } 0112 0113 /** 0114 * Sign a string with a given key and algorithm. 0115 * 0116 * @param string $msg The message to sign 0117 * @param string $key The secret key 0118 * @param string $method The signing algorithm. Supported 0119 * algorithms are 'HS256', 'HS384' and 'HS512' 0120 * 0121 * @return string An encrypted message 0122 * @throws DomainException Unsupported algorithm was specified 0123 */ 0124 public static function sign($msg, $key, $method = 'HS256') 0125 { 0126 $methods = array( 0127 'HS256' => 'sha256', 0128 'HS384' => 'sha384', 0129 'HS512' => 'sha512', 0130 ); 0131 if (empty($methods[$method])) { 0132 throw new DomainException('Algorithm not supported'); 0133 } 0134 0135 return hash_hmac($methods[$method], $msg, $key, true); 0136 } 0137 0138 /** 0139 * Converts and signs a PHP object or array into a JWT string. 0140 * 0141 * @param object|array $payload PHP object or array 0142 * @param string $key The secret key 0143 * @param string $algo The signing algorithm. Supported 0144 * algorithms are 'HS256', 'HS384' and 'HS512' 0145 * 0146 * @return string A signed JWT 0147 * @uses jsonEncode 0148 * @uses urlsafeB64Encode 0149 */ 0150 public static function encode($payload, $key, $algo = 'HS256') 0151 { 0152 $header = array('typ' => 'JWT', 'alg' => $algo); 0153 $segments = array(); 0154 $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($header)); 0155 $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($payload)); 0156 $signing_input = implode('.', $segments); 0157 $signature = JWT::sign($signing_input, $key, $algo); 0158 $segments[] = JWT::urlsafeB64Encode($signature); 0159 0160 return implode('.', $segments); 0161 } 0162 0163 /** 0164 * Encode a string with URL-safe Base64. 0165 * 0166 * @param string $input The string you want encoded 0167 * 0168 * @return string The base64 encode of what you passed in 0169 */ 0170 public static function urlsafeB64Encode($input) 0171 { 0172 return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); 0173 } 0174 0175 /** 0176 * Encode a PHP object into a JSON string. 0177 * 0178 * @param object|array $input A PHP object or array 0179 * 0180 * @return string JSON representation of the PHP object or array 0181 * @throws DomainException Provided object could not be encoded to valid JSON 0182 */ 0183 public static function jsonEncode($input) 0184 { 0185 $json = json_encode($input); 0186 if (function_exists('json_last_error') && $errno = json_last_error()) { 0187 JWT::_handleJsonError($errno); 0188 } else if ($json === 'null' && $input !== null) { 0189 throw new DomainException('Null result with non-null input'); 0190 } 0191 0192 return $json; 0193 } 0194 0195 public static function hashCode($a) 0196 { 0197 if ($a == null) { 0198 return 0; 0199 } 0200 0201 $result = crc32($a); 0202 0203 return $result; 0204 } 0205 0206 }