diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebecf08e..d1e34b33 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,6 @@ jobs: DB: ${{ matrix.database }} MOODLE_BRANCH: ${{ matrix.moodle-branch }} MUSTACHE_IGNORE_NAMES: 'mobile_view_page_latest.mustache,mobile_view_page_ionic3.mustache' - PHPDOC_IGNORE_PATHS: 'jwt' - name: PHP Lint if: ${{ always() }} diff --git a/README.md b/README.md index 9827428c..dfccf6cf 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,6 @@ Optional functionality can be enabled by granting additional scopes: - webinar:read:admin - webinar:write:admin -### JWT -JWT will be deprecated in June 2023. To create an account-level JWT app the 'JWT' permission is -required. - -You will need to [create a JWT app](https://developers.zoom.us/docs/platform/build/jwt-app/) and that will generate the API key and secret. - ## Installation 1. [Install plugin](https://docs.moodle.org/en/Installing_plugins#Installing_a_plugin) to the /mod/zoom folder in Moodle. @@ -54,13 +48,6 @@ You will need to [create a JWT app](https://developers.zoom.us/docs/platform/bui - Zoom client ID (mod_zoom | clientid) - Zoom client secret (mod_zoom | clientsecret) -JWT will be deprecated in June 2023. For a JWT app, you need to set the following settings to enable the plugin: - -- Zoom API key (mod_zoom | apikey) -- Zoom API secret (mod_zoom | apisecret) - -Please note that the API key and secret are not the same as the LTI key/secret. - If you get "Access token is expired" errors, make sure the date/time on your server is properly synchronized with the time servers. diff --git a/classes/webservice.php b/classes/webservice.php index 16e8b3c1..e47d5f63 100644 --- a/classes/webservice.php +++ b/classes/webservice.php @@ -27,21 +27,6 @@ require_once($CFG->dirroot . '/mod/zoom/locallib.php'); require_once($CFG->libdir . '/filelib.php'); -// Some plugins already might include this library, like mod_bigbluebuttonbn. -// Hacky, but need to create list of plugins that might have JWT library. -// NOTE: Remove file_exists checks and the JWT library in mod when versions prior to Moodle 3.7 is no longer supported. -if (!class_exists('Firebase\JWT\JWT')) { - if (file_exists($CFG->libdir . '/php-jwt/src/JWT.php')) { - require_once($CFG->libdir . '/php-jwt/src/JWT.php'); - } else { - if (file_exists($CFG->dirroot . '/mod/bigbluebuttonbn/vendor/firebase/php-jwt/src/JWT.php')) { - require_once($CFG->dirroot . '/mod/bigbluebuttonbn/vendor/firebase/php-jwt/src/JWT.php'); - } else { - require_once($CFG->dirroot . '/mod/zoom/jwt/JWT.php'); - } - } -} - /** * Web service class. */ @@ -85,18 +70,6 @@ class mod_zoom_webservice { */ protected $accountid; - /** - * API key - * @var string - */ - protected $apikey; - - /** - * API secret - * @var string - */ - protected $apisecret; - /** * API base URL. * @var string @@ -146,14 +119,6 @@ public function __construct() { 'accountid', ]; - // TODO: Remove when JWT is no longer supported in June 2023. - if (empty($config->clientid) || empty($config->clientsecret) || empty($config->accountid)) { - $requiredfields = [ - 'apikey', - 'apisecret', - ]; - } - try { // Get and remember each required field. foreach ($requiredfields as $requiredfield) { @@ -256,16 +221,7 @@ private function make_call($path, $data = [], $method = 'get') { $url = $this->apiurl . $path; $method = strtolower($method); - // TODO: Remove JWT auth when deprecated in June 2023. - if (isset($this->clientid) && isset($this->clientsecret) && isset($this->accountid)) { - $token = $this->get_access_token(); - } else { - $payload = [ - 'iss' => $this->apikey, - 'exp' => time() + 40, - ]; - $token = \Firebase\JWT\JWT::encode($payload, $this->apisecret, 'HS256'); - } + $token = $this->get_access_token(); $curl = $this->get_curl_object(); $curl->setHeader('Authorization: Bearer ' . $token); diff --git a/jwt/BeforeValidException.php b/jwt/BeforeValidException.php deleted file mode 100644 index d49ba712..00000000 --- a/jwt/BeforeValidException.php +++ /dev/null @@ -1,8 +0,0 @@ - - * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD - * @link https://github.com/firebase/php-jwt - */ -class JWK -{ - /** - * Parse a set of JWK keys - * - * @param array $jwks The JSON Web Key Set as an associative array - * - * @return array An associative array that represents the set of keys - * - * @throws InvalidArgumentException Provided JWK Set is empty - * @throws UnexpectedValueException Provided JWK Set was invalid - * @throws DomainException OpenSSL failure - * - * @uses parseKey - */ - public static function parseKeySet(array $jwks) - { - $keys = array(); - - if (!isset($jwks['keys'])) { - throw new UnexpectedValueException('"keys" member must exist in the JWK Set'); - } - if (empty($jwks['keys'])) { - throw new InvalidArgumentException('JWK Set did not contain any keys'); - } - - foreach ($jwks['keys'] as $k => $v) { - $kid = isset($v['kid']) ? $v['kid'] : $k; - if ($key = self::parseKey($v)) { - $keys[$kid] = $key; - } - } - - if (0 === \count($keys)) { - throw new UnexpectedValueException('No supported algorithms found in JWK Set'); - } - - return $keys; - } - - /** - * Parse a JWK key - * - * @param array $jwk An individual JWK - * - * @return resource|array An associative array that represents the key - * - * @throws InvalidArgumentException Provided JWK is empty - * @throws UnexpectedValueException Provided JWK was invalid - * @throws DomainException OpenSSL failure - * - * @uses createPemFromModulusAndExponent - */ - public static function parseKey(array $jwk) - { - if (empty($jwk)) { - throw new InvalidArgumentException('JWK must not be empty'); - } - if (!isset($jwk['kty'])) { - throw new UnexpectedValueException('JWK must contain a "kty" parameter'); - } - - switch ($jwk['kty']) { - case 'RSA': - if (!empty($jwk['d'])) { - throw new UnexpectedValueException('RSA private keys are not supported'); - } - if (!isset($jwk['n']) || !isset($jwk['e'])) { - throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"'); - } - - $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']); - $publicKey = \openssl_pkey_get_public($pem); - if (false === $publicKey) { - throw new DomainException( - 'OpenSSL error: ' . \openssl_error_string() - ); - } - return $publicKey; - default: - // Currently only RSA is supported - break; - } - } - - /** - * Create a public key represented in PEM format from RSA modulus and exponent information - * - * @param string $n The RSA modulus encoded in Base64 - * @param string $e The RSA exponent encoded in Base64 - * - * @return string The RSA public key represented in PEM format - * - * @uses encodeLength - */ - private static function createPemFromModulusAndExponent($n, $e) - { - $modulus = JWT::urlsafeB64Decode($n); - $publicExponent = JWT::urlsafeB64Decode($e); - - $components = array( - 'modulus' => \pack('Ca*a*', 2, self::encodeLength(\strlen($modulus)), $modulus), - 'publicExponent' => \pack('Ca*a*', 2, self::encodeLength(\strlen($publicExponent)), $publicExponent) - ); - - $rsaPublicKey = \pack( - 'Ca*a*a*', - 48, - self::encodeLength(\strlen($components['modulus']) + \strlen($components['publicExponent'])), - $components['modulus'], - $components['publicExponent'] - ); - - // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption. - $rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA - $rsaPublicKey = \chr(0) . $rsaPublicKey; - $rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey; - - $rsaPublicKey = \pack( - 'Ca*a*', - 48, - self::encodeLength(\strlen($rsaOID . $rsaPublicKey)), - $rsaOID . $rsaPublicKey - ); - - $rsaPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . - \chunk_split(\base64_encode($rsaPublicKey), 64) . - '-----END PUBLIC KEY-----'; - - return $rsaPublicKey; - } - - /** - * DER-encode the length - * - * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See - * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. - * - * @param int $length - * @return string - */ - private static function encodeLength($length) - { - if ($length <= 0x7F) { - return \chr($length); - } - - $temp = \ltrim(\pack('N', $length), \chr(0)); - - return \pack('Ca*', 0x80 | \strlen($temp), $temp); - } -} diff --git a/jwt/JWT.php b/jwt/JWT.php deleted file mode 100644 index 1044a1d6..00000000 --- a/jwt/JWT.php +++ /dev/null @@ -1,545 +0,0 @@ - - * @author Anant Narayanan - * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD - * @link https://github.com/firebase/php-jwt - */ -class JWT -{ - const ASN1_INTEGER = 0x02; - const ASN1_SEQUENCE = 0x10; - const ASN1_BIT_STRING = 0x03; - - /** - * When checking nbf, iat or expiration times, - * we want to provide some extra leeway time to - * account for clock skew. - */ - public static $leeway = 0; - - /** - * Allow the current timestamp to be specified. - * Useful for fixing a value within unit testing. - * - * Will default to PHP time() value if null. - */ - public static $timestamp = null; - - public static $supported_algs = array( - 'ES384' => array('openssl', 'SHA384'), - 'ES256' => array('openssl', 'SHA256'), - 'HS256' => array('hash_hmac', 'SHA256'), - 'HS384' => array('hash_hmac', 'SHA384'), - 'HS512' => array('hash_hmac', 'SHA512'), - 'RS256' => array('openssl', 'SHA256'), - 'RS384' => array('openssl', 'SHA384'), - 'RS512' => array('openssl', 'SHA512'), - 'EdDSA' => array('sodium_crypto', 'EdDSA'), - ); - - /** - * Decodes a JWT string into a PHP object. - * - * @param string $jwt The JWT - * @param string|array|resource $key The key, or map of keys. - * If the algorithm used is asymmetric, this is the public key - * @param array $allowed_algs List of supported verification algorithms - * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', - * 'HS512', 'RS256', 'RS384', and 'RS512' - * - * @return object The JWT's payload as a PHP object - * - * @throws InvalidArgumentException Provided JWT was empty - * @throws UnexpectedValueException Provided JWT was invalid - * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed - * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf' - * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat' - * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim - * - * @uses jsonDecode - * @uses urlsafeB64Decode - */ - public static function decode($jwt, $key, array $allowed_algs = array()) - { - $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp; - - if (empty($key)) { - throw new InvalidArgumentException('Key may not be empty'); - } - $tks = \explode('.', $jwt); - if (\count($tks) != 3) { - throw new UnexpectedValueException('Wrong number of segments'); - } - list($headb64, $bodyb64, $cryptob64) = $tks; - if (null === ($header = static::jsonDecode(static::urlsafeB64Decode($headb64)))) { - throw new UnexpectedValueException('Invalid header encoding'); - } - if (null === $payload = static::jsonDecode(static::urlsafeB64Decode($bodyb64))) { - throw new UnexpectedValueException('Invalid claims encoding'); - } - if (false === ($sig = static::urlsafeB64Decode($cryptob64))) { - throw new UnexpectedValueException('Invalid signature encoding'); - } - if (empty($header->alg)) { - throw new UnexpectedValueException('Empty algorithm'); - } - if (empty(static::$supported_algs[$header->alg])) { - throw new UnexpectedValueException('Algorithm not supported'); - } - if (!\in_array($header->alg, $allowed_algs)) { - throw new UnexpectedValueException('Algorithm not allowed'); - } - if ($header->alg === 'ES256' || $header->alg === 'ES384') { - // OpenSSL expects an ASN.1 DER sequence for ES256/ES384 signatures - $sig = self::signatureToDER($sig); - } - - if (\is_array($key) || $key instanceof \ArrayAccess) { - if (isset($header->kid)) { - if (!isset($key[$header->kid])) { - throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key'); - } - $key = $key[$header->kid]; - } else { - throw new UnexpectedValueException('"kid" empty, unable to lookup correct key'); - } - } - - // Check the signature - if (!static::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) { - throw new SignatureInvalidException('Signature verification failed'); - } - - // Check 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 > ($timestamp + static::$leeway)) { - 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 > ($timestamp + static::$leeway)) { - throw new BeforeValidException( - 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->iat) - ); - } - - // Check if this token has expired. - if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) { - throw new ExpiredException('Expired token'); - } - - return $payload; - } - - /** - * Converts and signs a PHP object or array into a JWT string. - * - * @param object|array $payload PHP object or array - * @param string|resource $key The secret key. - * If the algorithm used is asymmetric, this is the private key - * @param string $alg The signing algorithm. - * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', - * 'HS512', 'RS256', 'RS384', and 'RS512' - * @param mixed $keyId - * @param array $head An array with header elements to attach - * - * @return string A signed JWT - * - * @uses jsonEncode - * @uses urlsafeB64Encode - */ - public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null) - { - $header = array('typ' => 'JWT', 'alg' => $alg); - if ($keyId !== null) { - $header['kid'] = $keyId; - } - if (isset($head) && \is_array($head)) { - $header = \array_merge($head, $header); - } - $segments = array(); - $segments[] = static::urlsafeB64Encode(static::jsonEncode($header)); - $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload)); - $signing_input = \implode('.', $segments); - - $signature = static::sign($signing_input, $key, $alg); - $segments[] = static::urlsafeB64Encode($signature); - - return \implode('.', $segments); - } - - /** - * Sign a string with a given key and algorithm. - * - * @param string $msg The message to sign - * @param string|resource $key The secret key - * @param string $alg The signing algorithm. - * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', - * 'HS512', 'RS256', 'RS384', and 'RS512' - * - * @return string An encrypted message - * - * @throws DomainException Unsupported algorithm or bad key was specified - */ - public static function sign($msg, $key, $alg = 'HS256') - { - if (empty(static::$supported_algs[$alg])) { - throw new DomainException('Algorithm not supported'); - } - list($function, $algorithm) = static::$supported_algs[$alg]; - switch ($function) { - case 'hash_hmac': - return \hash_hmac($algorithm, $msg, $key, true); - case 'openssl': - $signature = ''; - $success = \openssl_sign($msg, $signature, $key, $algorithm); - if (!$success) { - throw new DomainException("OpenSSL unable to sign data"); - } - if ($alg === 'ES256') { - $signature = self::signatureFromDER($signature, 256); - } elseif ($alg === 'ES384') { - $signature = self::signatureFromDER($signature, 384); - } - return $signature; - case 'sodium_crypto': - if (!function_exists('sodium_crypto_sign_detached')) { - throw new DomainException('libsodium is not available'); - } - try { - // The last non-empty line is used as the key. - $lines = array_filter(explode("\n", $key)); - $key = base64_decode(end($lines)); - return sodium_crypto_sign_detached($msg, $key); - } catch (Exception $e) { - throw new DomainException($e->getMessage(), 0, $e); - } - } - } - - /** - * Verify a signature with the message, key and method. Not all methods - * are symmetric, so we must have a separate verify and sign method. - * - * @param string $msg The original message (header and body) - * @param string $signature The original signature - * @param string|resource $key For HS*, a string key works. for RS*, must be a resource of an openssl public key - * @param string $alg The algorithm - * - * @return bool - * - * @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure - */ - private static function verify($msg, $signature, $key, $alg) - { - if (empty(static::$supported_algs[$alg])) { - throw new DomainException('Algorithm not supported'); - } - - list($function, $algorithm) = static::$supported_algs[$alg]; - switch ($function) { - case 'openssl': - $success = \openssl_verify($msg, $signature, $key, $algorithm); - if ($success === 1) { - return true; - } elseif ($success === 0) { - return false; - } - // returns 1 on success, 0 on failure, -1 on error. - throw new DomainException( - 'OpenSSL error: ' . \openssl_error_string() - ); - case 'sodium_crypto': - if (!function_exists('sodium_crypto_sign_verify_detached')) { - throw new DomainException('libsodium is not available'); - } - try { - // The last non-empty line is used as the key. - $lines = array_filter(explode("\n", $key)); - $key = base64_decode(end($lines)); - return sodium_crypto_sign_verify_detached($signature, $msg, $key); - } catch (Exception $e) { - throw new DomainException($e->getMessage(), 0, $e); - } - case 'hash_hmac': - default: - $hash = \hash_hmac($algorithm, $msg, $key, true); - if (\function_exists('hash_equals')) { - return \hash_equals($signature, $hash); - } - $len = \min(static::safeStrlen($signature), static::safeStrlen($hash)); - - $status = 0; - for ($i = 0; $i < $len; $i++) { - $status |= (\ord($signature[$i]) ^ \ord($hash[$i])); - } - $status |= (static::safeStrlen($signature) ^ static::safeStrlen($hash)); - - return ($status === 0); - } - } - - /** - * Decode a JSON string into a PHP object. - * - * @param string $input JSON string - * - * @return object Object representation of JSON string - * - * @throws DomainException Provided string was invalid JSON - */ - public static function jsonDecode($input) - { - if (\version_compare(PHP_VERSION, '5.4.0', '>=') && !(\defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) { - /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you - * to specify that large ints (like Steam Transaction IDs) should be treated as - * strings, rather than the PHP default behaviour of converting them to floats. - */ - $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING); - } else { - /** Not all servers will support that, however, so for older versions we must - * manually detect large ints in the JSON string and quote them (thus converting - *them to strings) before decoding, hence the preg_replace() call. - */ - $max_int_length = \strlen((string) PHP_INT_MAX) - 1; - $json_without_bigints = \preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input); - $obj = \json_decode($json_without_bigints); - } - - if ($errno = \json_last_error()) { - static::handleJsonError($errno); - } elseif ($obj === null && $input !== 'null') { - throw new DomainException('Null result with non-null input'); - } - return $obj; - } - - /** - * Encode a PHP object into a JSON string. - * - * @param object|array $input A PHP object or array - * - * @return string JSON representation of the PHP object or array - * - * @throws DomainException Provided object could not be encoded to valid JSON - */ - public static function jsonEncode($input) - { - $json = \json_encode($input); - if ($errno = \json_last_error()) { - static::handleJsonError($errno); - } elseif ($json === 'null' && $input !== null) { - throw new DomainException('Null result with non-null input'); - } - return $json; - } - - /** - * Decode a string with URL-safe Base64. - * - * @param string $input A Base64 encoded string - * - * @return string A decoded string - */ - public static function urlsafeB64Decode($input) - { - $remainder = \strlen($input) % 4; - if ($remainder) { - $padlen = 4 - $remainder; - $input .= \str_repeat('=', $padlen); - } - return \base64_decode(\strtr($input, '-_', '+/')); - } - - /** - * Encode a string with URL-safe Base64. - * - * @param string $input The string you want encoded - * - * @return string The base64 encode of what you passed in - */ - public static function urlsafeB64Encode($input) - { - return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_')); - } - - /** - * Helper method to create a JSON error. - * - * @param int $errno An error number from json_last_error() - * - * @return void - */ - private static function handleJsonError($errno) - { - $messages = array( - JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', - JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON', - JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', - JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', - JSON_ERROR_UTF8 => 'Malformed UTF-8 characters' //PHP >= 5.3.3 - ); - throw new DomainException( - isset($messages[$errno]) - ? $messages[$errno] - : 'Unknown JSON error: ' . $errno - ); - } - - /** - * Get the number of bytes in cryptographic strings. - * - * @param string $str - * - * @return int - */ - private static function safeStrlen($str) - { - if (\function_exists('mb_strlen')) { - return \mb_strlen($str, '8bit'); - } - return \strlen($str); - } - - /** - * Convert an ECDSA signature to an ASN.1 DER sequence - * - * @param string $sig The ECDSA signature to convert - * @return string The encoded DER object - */ - private static function signatureToDER($sig) - { - // Separate the signature into r-value and s-value - list($r, $s) = \str_split($sig, (int) (\strlen($sig) / 2)); - - // Trim leading zeros - $r = \ltrim($r, "\x00"); - $s = \ltrim($s, "\x00"); - - // Convert r-value and s-value from unsigned big-endian integers to - // signed two's complement - if (\ord($r[0]) > 0x7f) { - $r = "\x00" . $r; - } - if (\ord($s[0]) > 0x7f) { - $s = "\x00" . $s; - } - - return self::encodeDER( - self::ASN1_SEQUENCE, - self::encodeDER(self::ASN1_INTEGER, $r) . - self::encodeDER(self::ASN1_INTEGER, $s) - ); - } - - /** - * Encodes a value into a DER object. - * - * @param int $type DER tag - * @param string $value the value to encode - * @return string the encoded object - */ - private static function encodeDER($type, $value) - { - $tag_header = 0; - if ($type === self::ASN1_SEQUENCE) { - $tag_header |= 0x20; - } - - // Type - $der = \chr($tag_header | $type); - - // Length - $der .= \chr(\strlen($value)); - - return $der . $value; - } - - /** - * Encodes signature from a DER object. - * - * @param string $der binary signature in DER format - * @param int $keySize the number of bits in the key - * @return string the signature - */ - private static function signatureFromDER($der, $keySize) - { - // OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE - list($offset, $_) = self::readDER($der); - list($offset, $r) = self::readDER($der, $offset); - list($offset, $s) = self::readDER($der, $offset); - - // Convert r-value and s-value from signed two's compliment to unsigned - // big-endian integers - $r = \ltrim($r, "\x00"); - $s = \ltrim($s, "\x00"); - - // Pad out r and s so that they are $keySize bits long - $r = \str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT); - $s = \str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT); - - return $r . $s; - } - - /** - * Reads binary DER-encoded data and decodes into a single object - * - * @param string $der the binary data in DER format - * @param int $offset the offset of the data stream containing the object - * to decode - * @return array [$offset, $data] the new offset and the decoded object - */ - private static function readDER($der, $offset = 0) - { - $pos = $offset; - $size = \strlen($der); - $constructed = (\ord($der[$pos]) >> 5) & 0x01; - $type = \ord($der[$pos++]) & 0x1f; - - // Length - $len = \ord($der[$pos++]); - if ($len & 0x80) { - $n = $len & 0x1f; - $len = 0; - while ($n-- && $pos < $size) { - $len = ($len << 8) | \ord($der[$pos++]); - } - } - - // Value - if ($type == self::ASN1_BIT_STRING) { - $pos++; // Skip the first contents octet (padding indicator) - $data = \substr($der, $pos, $len - 1); - $pos += $len - 1; - } elseif (!$constructed) { - $data = \substr($der, $pos, $len); - $pos += $len; - } else { - $data = null; - } - - return array($pos, $data); - } -} diff --git a/jwt/SignatureInvalidException.php b/jwt/SignatureInvalidException.php deleted file mode 100644 index e9cd53c7..00000000 --- a/jwt/SignatureInvalidException.php +++ /dev/null @@ -1,8 +0,0 @@ -add($clientsecret); - $apikey = new admin_setting_configtext('zoom/apikey', get_string('apikey', 'mod_zoom'), - get_string('apikey_desc', 'mod_zoom'), '', PARAM_ALPHANUMEXT); - $settings->add($apikey); - - $apisecret = new admin_setting_configpasswordunmask('zoom/apisecret', get_string('apisecret', 'mod_zoom'), - get_string('apisecret_desc', 'mod_zoom'), ''); - $settings->add($apisecret); - $zoomurl = new admin_setting_configtext('zoom/zoomurl', get_string('zoomurl', 'mod_zoom'), get_string('zoomurl_desc', 'mod_zoom'), '', PARAM_URL); $settings->add($zoomurl); diff --git a/tests/generator/lib.php b/tests/generator/lib.php index 55159e40..cf507501 100644 --- a/tests/generator/lib.php +++ b/tests/generator/lib.php @@ -35,9 +35,6 @@ public function create_instance($record = null, array $options = null) { set_config('clientid', 'test', 'zoom'); set_config('clientsecret', 'test', 'zoom'); set_config('accountid', 'test', 'zoom'); - // TODO: Remove with JWT deprecation June 2023. - set_config('apikey', 'test', 'zoom'); - set_config('apisecret', 'test', 'zoom'); // Mock Zoom data for testing. $defaultzoomsettings = [ diff --git a/tests/mod_zoom_webservice_test.php b/tests/mod_zoom_webservice_test.php index 3b964813..462bf00d 100644 --- a/tests/mod_zoom_webservice_test.php +++ b/tests/mod_zoom_webservice_test.php @@ -51,9 +51,6 @@ public function setUp(): void { set_config('clientid', 'test', 'zoom'); set_config('clientsecret', 'test', 'zoom'); set_config('accountid', 'test', 'zoom'); - // TODO: Remove with JWT deprecation June 2023. - set_config('apikey', 'test', 'zoom'); - set_config('apisecret', 'test', 'zoom'); $this->notfoundmockcurl = new class { // @codingStandardsIgnoreStart