public static function decode($jwt, $key = null, $allowedAlgs = array(), $extraSeconds = 0) { $tks = explode('.', $jwt); if (count($tks) != 3) { throw new \UnexpectedValueException('Wrong number of segments'); } list($headb64, $bodyb64, $cryptob64) = $tks; if (null === ($header = json_decode(JWT::urlsafeB64Decode($headb64)))) { throw new \UnexpectedValueException('Invalid header encoding'); } if (null === ($payload = json_decode(JWT::urlsafeB64Decode($bodyb64)))) { throw new \UnexpectedValueException('Invalid claims encoding'); } $sig = JWT::urlsafeB64Decode($cryptob64); if (isset($key)) { if (empty($header->alg)) { throw new \DomainException('Empty algorithm'); } if (empty(self::$supportedAlgs[$header->alg])) { throw new \DomainException('Algorithm not supported'); } if (!is_array($allowedAlgs) || !in_array($header->alg, $allowedAlgs)) { throw new \DomainException('Algorithm not allowed'); } if (is_array($key)) { if (isset($header->kid)) { $key = $key[$header->kid]; } else { throw new \DomainException('"kid" empty, unable to lookup correct key'); } } if (!JWT::verify("{$headb64}.{$bodyb64}", $sig, $key, $header->alg)) { throw new SignatureInvalidException('Signature verification failed'); } // Check if the nbf if it is defined. This is the time that the // token can actually be used. If it's not yet that time, abort. if (isset($payload->nbf) && $payload->nbf > time()) { throw new BeforeValidException('Cannot handle token prior to ' . date(\DateTime::ISO8601, $payload->nbf)); } // Check that this token has been created before 'now'. This prevents // using tokens that have been created for later use (and haven't // correctly used the nbf claim). if (isset($payload->iat) && $payload->iat > time()) { throw new BeforeValidException('Cannot handle token prior to ' . date(\DateTime::ISO8601, $payload->iat)); } // Check if this token has expired. if (isset($payload->exp) && time() >= $payload->exp + $extraSeconds) { throw new ExpiredException('Expired token'); } } return $payload; }