File indexing completed on 2024-12-22 05:33:15
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 { 0072 if ($obj === null && $input !== 'null') { 0073 throw new DomainException('Null result with non-null input'); 0074 } 0075 } 0076 0077 return $obj; 0078 } 0079 0080 /** 0081 * Helper method to create a JSON error. 0082 * 0083 * @param int $errno An error number from json_last_error() 0084 * 0085 * @return void 0086 */ 0087 private static function _handleJsonError($errno) 0088 { 0089 $messages = array( 0090 JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', 0091 JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', 0092 JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON' 0093 ); 0094 throw new DomainException(isset($messages[$errno]) ? $messages[$errno] : 'Unknown JSON error: ' . $errno); 0095 } 0096 0097 /** 0098 * Decode a string with URL-safe Base64. 0099 * 0100 * @param string $input A Base64 encoded string 0101 * 0102 * @return string A decoded string 0103 */ 0104 public static function urlsafeB64Decode($input) 0105 { 0106 $remainder = strlen($input) % 4; 0107 if ($remainder) { 0108 $padlen = 4 - $remainder; 0109 $input .= str_repeat('=', $padlen); 0110 } 0111 0112 return base64_decode(strtr($input, '-_', '+/')); 0113 } 0114 0115 /** 0116 * Sign a string with a given key and algorithm. 0117 * 0118 * @param string $msg The message to sign 0119 * @param string $key The secret key 0120 * @param string $method The signing algorithm. Supported 0121 * algorithms are 'HS256', 'HS384' and 'HS512' 0122 * 0123 * @return string An encrypted message 0124 * @throws DomainException Unsupported algorithm was specified 0125 */ 0126 public static function sign($msg, $key, $method = 'HS256') 0127 { 0128 $methods = array( 0129 'HS256' => 'sha256', 0130 'HS384' => 'sha384', 0131 'HS512' => 'sha512', 0132 ); 0133 if (empty($methods[$method])) { 0134 throw new DomainException('Algorithm not supported'); 0135 } 0136 0137 return hash_hmac($methods[$method], $msg, $key, true); 0138 } 0139 0140 /** 0141 * Converts and signs a PHP object or array into a JWT string. 0142 * 0143 * @param object|array $payload PHP object or array 0144 * @param string $key The secret key 0145 * @param string $algo The signing algorithm. Supported 0146 * algorithms are 'HS256', 'HS384' and 'HS512' 0147 * 0148 * @return string A signed JWT 0149 * @uses jsonEncode 0150 * @uses urlsafeB64Encode 0151 */ 0152 public static function encode($payload, $key, $algo = 'HS256') 0153 { 0154 $header = array('typ' => 'JWT', 'alg' => $algo); 0155 $segments = array(); 0156 $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($header)); 0157 $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($payload)); 0158 $signing_input = implode('.', $segments); 0159 $signature = JWT::sign($signing_input, $key, $algo); 0160 $segments[] = JWT::urlsafeB64Encode($signature); 0161 0162 return implode('.', $segments); 0163 } 0164 0165 /** 0166 * Encode a string with URL-safe Base64. 0167 * 0168 * @param string $input The string you want encoded 0169 * 0170 * @return string The base64 encode of what you passed in 0171 */ 0172 public static function urlsafeB64Encode($input) 0173 { 0174 return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); 0175 } 0176 0177 /** 0178 * Encode a PHP object into a JSON string. 0179 * 0180 * @param object|array $input A PHP object or array 0181 * 0182 * @return string JSON representation of the PHP object or array 0183 * @throws DomainException Provided object could not be encoded to valid JSON 0184 */ 0185 public static function jsonEncode($input) 0186 { 0187 $json = json_encode($input); 0188 if (function_exists('json_last_error') && $errno = json_last_error()) { 0189 JWT::_handleJsonError($errno); 0190 } else { 0191 if ($json === 'null' && $input !== null) { 0192 throw new DomainException('Null result with non-null input'); 0193 } 0194 } 0195 0196 return $json; 0197 } 0198 0199 public static function hashCode($a) 0200 { 0201 if ($a == null) { 0202 return 0; 0203 } 0204 0205 $result = crc32($a); 0206 0207 return $result; 0208 } 0209 0210 }