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;
 }