. namespace auth_jwt; require_once(__DIR__ . '/../vendor/autoload.php'); use \Firebase\JWT\JWT; /** * Key manager class. * * @package auth_jwt * @copyright 2016 Dmitrii Metelkin (dmitriim@catalyst-au.net), 2024 Kumi Systems e.U. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class core_jwt_manager { /** * Default life time of the user key in seconds. */ const DEFAULT_KEY_LIFE_TIME_IN_SECONDS = 60; /** * Config object. * * @var \stdClass */ protected $config; /** * Constructor. * * @param \stdClass $config */ public function __construct(\stdClass $config) { $this->config = $config; } /** * Create a user key. * * @param int $userid User ID. * @param null|array $allowedips A list of allowed ips for this key. * * @return string Generated key. */ public function create_key($userid, $allowedips = null) { if (isset($this->config->keylifetime) && (int)$this->config->keylifetime > 0) { $validuntil = time() + $this->config->keylifetime; } else { $validuntil = time() + self::DEFAULT_KEY_LIFE_TIME_IN_SECONDS; } $payload = [ 'userid' => $userid, 'exp' => $validuntil ]; if ($allowedips) { $payload['allowedips'] = $allowedips; } $secret = $this->config->jwtsecret; return JWT::encode($payload, $secret); } /** * Validates key and returns key data object if valid. * * @param string $keyvalue User key value. * * @return object Key object including userid property. * * @throws \moodle_exception If provided key is not valid. */ public function validate_key($keyvalue) { $secret = $this->config->jwtsecret; try { $decoded = JWT::decode($keyvalue, $secret, ['HS256']); } catch (\Exception $e) { throw new \moodle_exception('invalidkey'); } if (!empty($decoded->exp) && $decoded->exp < time()) { throw new \moodle_exception('expiredkey'); } $this->validate_ip_address($decoded); return $decoded; } /** * Validates key IP address and returns true if valid. * * @param object $key Key object including userid property. * * @throws \moodle_exception If provided key is not valid. */ protected function validate_ip_address($key) { if (empty($key->allowedips)) { return true; } $remoteaddr = getremoteaddr(null); if (empty($remoteaddr)) { throw new \moodle_exception('noip', 'auth_jwt'); } foreach ($key->allowedips as $allowedip) { if (address_in_subnet($remoteaddr, $allowedip)) { return true; } } throw new \moodle_exception('ipmismatch', 'error', '', null, "Remote address: $remoteaddr\nKey IP: " . implode(', ', $key->allowedips)); } }