. namespace auth_jwt; use advanced_testcase; use auth_plugin_jwt; use stdClass; use invalid_parameter_exception; use moodle_exception; use external_value; /** * Tests for auth_plugin_jwt class. * * @covers \auth_plugin_jwt * * @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 auth_plugin_test extends advanced_testcase { /** * An instance of auth_plugin_jwt class. * @var auth_plugin_jwt */ protected $auth; /** * User object. * @var */ protected $user; /** * Path used for the redirection. * @var string */ const REDIRECTION_PATH = "/redirection"; /** * Initial set up. */ public function setUp(): void { global $CFG; require_once($CFG->libdir . "/externallib.php"); require_once($CFG->dirroot . '/auth/jwt/tests/fake_jwt_manager.php'); require_once($CFG->dirroot . '/auth/jwt/auth.php'); require_once($CFG->dirroot . '/user/lib.php'); parent::setUp(); $this->resetAfterTest(); $CFG->getremoteaddrconf = GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR; $this->auth = new auth_plugin_jwt(); $this->user = self::getDataGenerator()->create_user(); } /** * A helper function to create TestKey. * * @param array $record Key record. */ protected function create_user_private_key(array $record = []) { global $DB; $record = (object)$record; if (!isset($record->value)) { $record->value = 'TestKey'; } if (!isset($record->userid)) { $record->userid = $this->user->id; } if (!isset($record->userid)) { $record->instance = $this->user->id; } if (!isset($record->iprestriction)) { $record->iprestriction = null; } if (!isset($record->validuntil)) { $record->validuntil = time() + 300; } if (!isset($record->timecreated)) { $record->timecreated = time(); } $record->script = 'auth/jwt'; $DB->insert_record('user_private_key', $record); } /** * Test that users can't login using login form. */ public function test_users_can_not_login_using_login_form() { $user = new stdClass(); $user->auth = 'jwt'; $user->username = 'username'; $user->password = 'correctpassword'; self::getDataGenerator()->create_user($user); $this->assertFalse($this->auth->user_login('username', 'correctpassword')); $this->assertFalse($this->auth->user_login('username', 'incorrectpassword')); } /** * Test that the plugin doesn't allow to store users passwords. */ public function test_auth_plugin_does_not_allow_to_store_passwords() { $this->assertTrue($this->auth->prevent_local_passwords()); } /** * Test that the plugin is external. */ public function test_auth_plugin_is_external() { $this->assertFalse($this->auth->is_internal()); } /** * Test that the plugin doesn't allow users to change the passwords. */ public function test_auth_plugin_does_not_allow_to_change_passwords() { $this->assertFalse($this->auth->can_change_password()); } /** * Test that default mapping field gets returned correctly. */ public function test_get_default_mapping_field() { $expected = 'email'; $actual = $this->auth->get_mapping_field(); $this->assertEquals($expected, $actual); } /** * Test that logout page hook sets global redirect variable correctly. */ public function test_logoutpage_hook_sets_global_redirect_correctly() { global $redirect, $SESSION; $this->auth->logoutpage_hook(); $this->assertEquals('', $redirect); $SESSION->jwt = true; $this->auth = new auth_plugin_jwt(); $this->auth->logoutpage_hook(); $this->assertEquals('', $redirect); unset($SESSION->jwt); set_config('redirecturl', 'http://example.com', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->auth->logoutpage_hook(); $this->assertEquals('', $redirect); $SESSION->jwt = true; set_config('redirecturl', 'http://example.com', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->auth->logoutpage_hook(); $this->assertEquals('http://example.com', $redirect); } /** * Test that configured mapping field gets returned correctly. */ public function test_get_mapping_field() { set_config('mappingfield', 'username', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = 'username'; $actual = $this->auth->get_mapping_field(); $this->assertEquals($expected, $actual); } /** * Test that auth plugin throws correct exception if default mapping field is not provided. */ public function test_throwing_exception_if_default_mapping_field_is_not_provided() { $user = array(); $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Invalid parameter value detected (Required field "email" is not set or empty.)'); $actual = $this->auth->get_login_url($user); } /** * Test that auth plugin throws correct exception if username mapping field is not provided, but set in configs. */ public function test_throwing_exception_if_mapping_field_username_is_not_provided() { $user = array(); set_config('mappingfield', 'username', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Invalid parameter value detected (Required field "username" is not set or empty.)'); $actual = $this->auth->get_login_url($user); } /** * Test that auth plugin throws correct exception if idnumber mapping field is not provided, but set in configs. */ public function test_throwing_exception_if_mapping_field_idnumber_is_not_provided() { $user = array(); set_config('mappingfield', 'idnumber', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Invalid parameter value detected (Required field "idnumber" is not set or empty.)'); $actual = $this->auth->get_login_url($user); } /** * Test that auth plugin throws correct exception if we trying to request not existing user. */ public function test_throwing_exception_if_user_is_not_exist() { $user = array(); $user['email'] = 'notexists@test.com'; $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Invalid parameter value detected (User is not exist)'); $actual = $this->auth->get_login_url($user); } /** * Test that auth plugin throws correct exception if we trying to request user, * but ip field is not set and iprestriction is enabled. */ public function test_throwing_exception_if_iprestriction_is_enabled_but_ip_is_missing_in_data() { $user = array(); $user['email'] = 'exists@test.com'; set_config('iprestriction', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Invalid parameter value detected (Required parameter "ip" is not set.)'); $actual = $this->auth->get_login_url($user); } /** * Test that we can request a user provided user data as an array. */ public function test_return_correct_login_url_if_user_is_array() { global $CFG; $user = array(); $user['username'] = 'username'; $user['email'] = 'exists@test.com'; self::getDataGenerator()->create_user($user); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $expected = $CFG->wwwroot . '/auth/jwt/login.php?key=FaKeKeyFoRtEsTiNg'; $actual = $this->auth->get_login_url($user); $this->assertEquals($expected, $actual); } /** * Test that we can request a user provided user data as an object. */ public function test_return_correct_login_url_if_user_is_object() { global $CFG; $user = new stdClass(); $user->username = 'username'; $user->email = 'exists@test.com'; self::getDataGenerator()->create_user($user); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $expected = $CFG->wwwroot . '/auth/jwt/login.php?key=FaKeKeyFoRtEsTiNg'; $actual = $this->auth->get_login_url($user); $this->assertEquals($expected, $actual); } /** * Test that we can request a user provided user data as an object. */ public function test_return_correct_login_url_if_iprestriction_is_enabled_and_data_is_correct() { global $CFG; $user = new stdClass(); $user->username = 'username'; $user->email = 'exists@test.com'; $user->ip = '192.168.1.1'; self::getDataGenerator()->create_user($user); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $expected = $CFG->wwwroot . '/auth/jwt/login.php?key=FaKeKeyFoRtEsTiNg'; $actual = $this->auth->get_login_url($user); $this->assertEquals($expected, $actual); } /** * Test that we can request a key for a new user. */ public function test_return_correct_login_url_and_create_new_user() { global $CFG, $DB; set_config('createuser', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $user = new stdClass(); $user->username = 'username'; $user->email = 'username@test.com'; $user->firstname = 'user'; $user->lastname = 'name'; $user->ip = '192.168.1.1'; $expected = $CFG->wwwroot . '/auth/jwt/login.php?key=FaKeKeyFoRtEsTiNg'; $actual = $this->auth->get_login_url($user); $this->assertEquals($expected, $actual); $userrecord = $DB->get_record('user', ['username' => 'username']); $this->assertEquals($user->email, $userrecord->email); $this->assertEquals($user->firstname, $userrecord->firstname); $this->assertEquals($user->lastname, $userrecord->lastname); $this->assertEquals(1, $userrecord->confirmed); $this->assertEquals('jwt', $userrecord->auth); } /** * Test that we can request a key for a new user. */ public function test_missing_data_to_create_user() { global $CFG, $DB; set_config('createuser', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $user = new stdClass(); $user->email = 'username@test.com'; $user->ip = '192.168.1.1'; $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Unable to create user, missing value(s): username,firstname,lastname'); $this->auth->get_login_url($user); } /** * Test that when we attempt to create a new user duplicate usernames are caught. */ public function test_create_refuse_duplicate_username() { set_config('createuser', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $originaluser = new stdClass(); $originaluser->username = 'username'; $originaluser->email = 'username@test.com'; $originaluser->firstname = 'user'; $originaluser->lastname = 'name'; $originaluser->city = 'brighton'; $originaluser->ip = '192.168.1.1'; self::getDataGenerator()->create_user($originaluser); $duplicateuser = clone ($originaluser); $duplicateuser->email = 'duplicateuser@test.com'; $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Username already exists: username'); $this->auth->get_login_url($duplicateuser); } /** * Test that when we attempt to create a new user duplicate emails are caught. */ public function test_create_refuse_duplicate_email() { set_config('createuser', true, 'auth_jwt'); set_config('mappingfield', 'username', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $originaluser = new stdClass(); $originaluser->username = 'username'; $originaluser->email = 'username@test.com'; $originaluser->firstname = 'user'; $originaluser->lastname = 'name'; $originaluser->city = 'brighton'; $originaluser->ip = '192.168.1.1'; self::getDataGenerator()->create_user($originaluser); $duplicateuser = clone ($originaluser); $duplicateuser->username = 'duplicateuser'; $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Email address already exists: username@test.com'); $this->auth->get_login_url($duplicateuser); } /** * Test that we can request a key for an existing user and update their details. */ public function test_return_correct_login_url_and_update_user() { global $CFG, $DB; set_config('updateuser', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); $originaluser = new stdClass(); $originaluser->username = 'username'; $originaluser->email = 'username@test.com'; $originaluser->firstname = 'user'; $originaluser->lastname = 'name'; $originaluser->city = 'brighton'; $originaluser->ip = '192.168.1.1'; self::getDataGenerator()->create_user($originaluser); $user = new stdClass(); $user->username = 'usernamechanged'; $user->email = 'username@test.com'; $user->firstname = 'userchanged'; $user->lastname = 'namechanged'; $user->ip = '192.168.1.1'; $expected = $CFG->wwwroot . '/auth/jwt/login.php?key=FaKeKeyFoRtEsTiNg'; $actual = $this->auth->get_login_url($user); $this->assertEquals($expected, $actual); $userrecord = $DB->get_record('user', ['email' => $user->email]); $this->assertEquals($user->username, $userrecord->username); $this->assertEquals($user->firstname, $userrecord->firstname); $this->assertEquals($user->lastname, $userrecord->lastname); $this->assertEquals($originaluser->city, $userrecord->city); $this->assertEquals('jwt', $userrecord->auth); } /** * Test that when we attempt to update a user duplicate emails are caught. */ public function test_update_refuse_duplicate_email() { set_config('updateuser', true, 'auth_jwt'); set_config('mappingfield', 'username', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); self::getDataGenerator()->create_user(['email' => 'trytoduplicate@test.com']); self::getDataGenerator()->create_user(['username' => 'username']); $originaluser = new stdClass(); $originaluser->username = 'username'; $originaluser->email = 'trytoduplicate@test.com'; $originaluser->firstname = 'user'; $originaluser->lastname = 'name'; $originaluser->city = 'brighton'; $originaluser->ip = '192.168.1.1'; $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Email address already exists: trytoduplicate@test.com'); $this->auth->get_login_url($originaluser); } /** * Test that when we attempt to update a user duplicate usernames are caught. */ public function test_update_refuse_duplicate_username() { set_config('updateuser', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $jwtmanager = new fake_jwt_manager(); $this->auth->set_jwt_manager($jwtmanager); self::getDataGenerator()->create_user(['username' => 'trytoduplicate']); self::getDataGenerator()->create_user(['email' => 'username@test.com']); $originaluser = new stdClass(); $originaluser->username = 'trytoduplicate'; $originaluser->email = 'username@test.com'; $originaluser->firstname = 'user'; $originaluser->lastname = 'name'; $originaluser->city = 'brighton'; $originaluser->ip = '192.168.1.1'; $this->expectException(invalid_parameter_exception::class); $this->expectExceptionMessage('Username already exists: trytoduplicate'); $this->auth->get_login_url($originaluser); } /** * Test that we can get login url if we do not use fake keymanager. */ public function test_return_correct_login_url_if_user_is_object_using_default_keymanager() { global $DB, $CFG; $user = array(); $user['username'] = 'username'; $user['email'] = 'exists@test.com'; $user = self::getDataGenerator()->create_user($user); create_user_key('auth/jwt', $user->id); create_user_key('auth/jwt', $user->id); create_user_key('auth/jwt', $user->id); $keys = $DB->get_records('user_private_key', array('userid' => $user->id)); $this->assertEquals(3, count($keys)); $actual = $this->auth->get_login_url($user); $keys = $DB->get_records('user_private_key', array('userid' => $user->id)); $this->assertEquals(1, count($keys)); $actualkey = $DB->get_record('user_private_key', array('userid' => $user->id)); $expected = $CFG->wwwroot . '/auth/jwt/login.php?key=' . $actualkey->value; $this->assertEquals($expected, $actual); } /** * Test that we can return correct allowed mapping fields. */ public function test_get_allowed_mapping_fields_list() { $expected = array( 'username' => 'Username', 'email' => 'Email address', 'idnumber' => 'ID number', ); $actual = $this->auth->get_allowed_mapping_fields(); $this->assertEquals($expected, $actual); } /** * Test that we can get correct request parameters based on the plugin configuration. */ public function test_get_request_login_url_user_parameters_based_on_plugin_config() { // Check email as it should be set by default. $expected = array( 'email' => new external_value( PARAM_EMAIL, 'A valid email address' ), ); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); // Check username. set_config('mappingfield', 'username', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = array( 'username' => new external_value( PARAM_USERNAME, 'Username' ), ); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); // Check idnumber. set_config('mappingfield', 'idnumber', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = array( 'idnumber' => new external_value( PARAM_RAW, 'An arbitrary ID code number perhaps from the institution' ), ); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); // Check some junk field name. set_config('mappingfield', 'junkfield', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = array(); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); // Check IP if iprestriction disabled. set_config('iprestriction', false, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = array(); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); // Check IP if iprestriction enabled. set_config('iprestriction', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = array( 'ip' => new external_value( PARAM_HOST, 'User IP address' ), ); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); // Check IP if createuser enabled. set_config('createuser', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = array( 'ip' => new external_value(PARAM_HOST, 'User IP address'), 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL), 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL), 'email' => new external_value(PARAM_RAW_TRIMMED, 'A valid and unique email address', VALUE_OPTIONAL), 'username' => new external_value(PARAM_USERNAME, 'A valid and unique username', VALUE_OPTIONAL), ); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); set_config('createuser', false, 'auth_jwt'); // Check IP if updateuser enabled. set_config('updateuser', true, 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $expected = array( 'ip' => new external_value(PARAM_HOST, 'User IP address'), 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL), 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL), 'email' => new external_value(PARAM_RAW_TRIMMED, 'A valid and unique email address', VALUE_OPTIONAL), 'username' => new external_value(PARAM_USERNAME, 'A valid and unique username', VALUE_OPTIONAL), ); $actual = $this->auth->get_request_login_url_user_parameters(); $this->assertEquals($expected, $actual); set_config('updateuser', false, 'auth_jwt'); } /** * Data provider for testing URL validation functions. * * @return array First element URL, the second URL is error message. Empty error massage means no errors. */ public function url_data_provider() { return array( array('', ''), array('http://google.com/', ''), array('https://google.com', ''), array('http://some.very.long.and.silly.domain/with/a/path/', ''), array('http://0.255.1.1/numericip.php', ''), array('http://0.255.1.1/numericip.php?test=1&id=2', ''), array('/just/a/path', 'You should provide valid URL'), array('random string', 'You should provide valid URL'), array(123456, 'You should provide valid URL'), array('php://google.com', 'You should provide valid URL'), ); } /** * Test required parameter exception gets thrown id try to login, but key is not set. */ public function test_required_parameter_exception_thrown_if_key_not_set() { $this->expectException(moodle_exception::class); $this->expectExceptionMessage('A required parameter (key) was missing'); $this->auth->user_login_jwt(); } /** * Test that incorrect key exception gets thrown if a key is incorrect. */ public function test_invalid_key_exception_thrown_if_invalid_key() { $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Incorrect key'); $_POST['key'] = 'InvalidKey'; $this->auth->user_login_jwt(); } /** * Test that expired key exception gets thrown if a key is expired. */ public function test_expired_key_exception_thrown_if_expired_key() { $this->create_user_private_key(['validuntil' => time() - 3000]); $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Expired key'); $_POST['key'] = 'TestKey'; $this->auth->user_login_jwt(); } /** * Test that IP address mismatch exception gets thrown if incorrect IP. */ public function test_ipmismatch_exception_thrown_if_ip_is_incorrect() { $this->create_user_private_key(['iprestriction' => '192.168.1.1']); $_POST['key'] = 'TestKey'; $_SERVER['HTTP_CLIENT_IP'] = '192.168.1.2'; $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Client IP address mismatch'); $this->auth->user_login_jwt(); } /** * Test that IP address mismatch exception gets thrown if incorrect IP and outside whitelist. */ public function test_ipmismatch_exception_thrown_if_ip_is_outside_whitelist() { set_config('ipwhitelist', '10.0.0.0/8;172.16.0.0/12;192.168.0.0/16', 'auth_jwt'); $this->create_user_private_key(['iprestriction' => '192.161.1.1']); $_POST['key'] = 'TestKey'; $_SERVER['HTTP_CLIENT_IP'] = '192.161.1.2'; $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Client IP address mismatch'); $this->auth->user_login_jwt(); } /** * Test that IP address mismatch exception gets thrown if user id is incorrect. */ public function test_invalid_user_exception_thrown_if_user_is_invalid() { $this->create_user_private_key([ 'userid' => 777, 'instance' => 777, 'iprestriction' => '192.168.1.1', ]); $_POST['key'] = 'TestKey'; $_SERVER['HTTP_CLIENT_IP'] = '192.168.1.1'; $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Invalid user'); $this->auth->user_login_jwt(); } /** * Test that key gets removed after a user logged in. */ public function test_that_key_gets_removed_after_user_logged_in() { global $DB; $this->create_user_private_key([ 'value' => 'RemoveKey', 'iprestriction' => '192.168.1.1', ]); $_POST['key'] = 'RemoveKey'; $_SERVER['HTTP_CLIENT_IP'] = '192.168.1.1'; try { // Using @ is the only way to test this. Thanks moodle! @$this->auth->user_login_jwt(); } catch (moodle_exception $e) { $keyexists = $DB->record_exists('user_private_key', array('value' => 'RemoveKey')); $this->assertFalse($keyexists); } } /** * Test that a user logs in and gets redirected correctly. */ public function test_that_user_logged_in_and_redirected() { global $CFG; $this->create_user_private_key(); $CFG->wwwroot = 'http://www.example.com/moodle'; $_POST['key'] = 'TestKey'; $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Unsupported redirect to http://www.example.com/moodle detected, execution terminated'); @$this->auth->user_login_jwt(); } /** * Test that a user logs in correctly. */ public function test_that_user_logged_in_correctly() { global $USER, $SESSION; $this->create_user_private_key(); $_POST['key'] = 'TestKey'; try { // Using @ is the only way to test this. Thanks moodle! @$this->auth->user_login_jwt(); } catch (moodle_exception $e) { $this->assertEquals($this->user->id, $USER->id); $this->assertSame(sesskey(), $USER->sesskey); $this->assertObjectHasAttribute('jwt', $SESSION); } } /** * Test that a user gets redirected to internal wantsurl URL successful log in. */ public function test_that_user_gets_redirected_to_internal_wantsurl() { $this->create_user_private_key(); $_POST['key'] = 'TestKey'; $_POST['wantsurl'] = '/course/index.php?id=12&key=134'; $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Unsupported redirect to /course/index.php?id=12&key=134 detected, execution terminated'); // Using @ is the only way to test this. Thanks moodle! @$this->auth->user_login_jwt(); } /** * Test that a user gets redirected to external wantsurl URL successful log in. */ public function test_that_user_gets_redirected_to_external_wantsurl() { $this->create_user_private_key(); $_POST['key'] = 'TestKey'; $_POST['wantsurl'] = 'http://test.com/course/index.php?id=12&key=134'; $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Unsupported redirect to http://test.com/course/index.php?id=12&key=134 detected, execution terminated'); // Using @ is the only way to test this. Thanks moodle! @$this->auth->user_login_jwt(); } /** * Test that login hook redirects a user if skipsso not set and ssourl is set. */ public function test_loginpage_hook_redirects_if_skipsso_not_set_and_ssourl_set() { global $SESSION; $SESSION->enrolkey_skipsso = 0; set_config('ssourl', 'http://google.com', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Unsupported redirect to http://google.com detected, execution terminated.'); $this->auth->loginpage_hook(); } /** * Test that login hook does not redirect a user if skipsso not set and ssourl is not set. */ public function test_loginpage_hook_does_not_redirect_if_skipsso_not_set_and_ssourl_not_set() { global $SESSION; $SESSION->enrolkey_skipsso = 0; set_config('ssourl', '', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->assertTrue($this->auth->loginpage_hook()); } /** * Test that login hook does not redirect a user if skipsso is set and ssourl is not set. */ public function test_loginpage_hook_does_not_redirect_if_skipsso_set_and_ssourl_not_set() { global $SESSION; $SESSION->enrolkey_skipsso = 1; set_config('ssourl', '', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->assertTrue($this->auth->loginpage_hook()); } /** * Test that pre login hook redirects a user if skipsso not set and ssourl is set. */ public function test_pre_loginpage_hook_redirects_if_skipsso_not_set_and_ssourl_set() { global $SESSION; $SESSION->enrolkey_skipsso = 0; set_config('ssourl', 'http://google.com', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->expectException(moodle_exception::class); $this->expectExceptionMessage('Unsupported redirect to http://google.com detected, execution terminated.'); $this->auth->pre_loginpage_hook(); } /** * Test that pre login hook does not redirect a user if skipsso is not set and ssourl is not set. */ public function test_pre_loginpage_hook_does_not_redirect_if_skipsso_not_set_and_ssourl_not_set() { global $SESSION; $SESSION->enrolkey_skipsso = 0; set_config('ssourl', '', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->assertTrue($this->auth->pre_loginpage_hook()); } /** * Test that login page hook does not redirect a user if skipsso is set and ssourl is not set. */ public function test_pre_loginpage_hook_does_not_redirect_if_skipsso_set_and_ssourl_not_set() { global $SESSION; $SESSION->enrolkey_skipsso = 1; set_config('ssourl', '', 'auth_jwt'); $this->auth = new auth_plugin_jwt(); $this->assertTrue($this->auth->pre_loginpage_hook()); } /** * Test that if one user logged, he will be logged out before a new one is authorised. */ public function test_that_different_authorised_user_is_logged_out_and_new_one_logged_in() { global $USER, $SESSION; $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $this->assertEquals($USER->id, $user->id); $this->create_user_private_key(); $_POST['key'] = 'TestKey'; try { // Using @ is the only way to test this. Thanks moodle! @$this->auth->user_login_jwt(); } catch (moodle_exception $e) { $this->assertEquals($this->user->id, $USER->id); $this->assertSame(sesskey(), $USER->sesskey); $this->assertObjectHasAttribute('jwt', $SESSION); } } /** * Test that authorised user gets logged out when trying to logged in with invalid key. */ public function test_if_invalid_key_authorised_user_gets_logged_out() { global $USER, $SESSION; $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $this->assertEquals($USER->id, $user->id); $this->create_user_private_key(); $_POST['key'] = 'Incorrect Key'; try { // Using @ is the only way to test this. Thanks moodle! @$this->auth->user_login_jwt(); } catch (moodle_exception $e) { $this->assertEquals('Incorrect key', $e->getMessage()); $this->assertEmpty($USER->id); $this->assertEquals(new stdClass(), $SESSION); } } /** * Test if a user is logged in and tries to log in again it stays logged in. */ public function test_that_already_logged_in_user_stays_logged_in() { global $DB, $USER, $SESSION; $this->setUser($this->user); $this->assertEquals($USER->id, $this->user->id); $this->create_user_private_key(); $_POST['key'] = 'TestKey'; try { // Using @ is the only way to test this. Thanks moodle! @$this->auth->user_login_jwt(); } catch (moodle_exception $e) { $this->assertEquals($this->user->id, $USER->id); $this->assertSame(sesskey(), $USER->sesskey); $this->assertObjectNotHasAttribute('jwt', $SESSION); $keyexists = $DB->record_exists('user_private_key', array('value' => 'TestKey')); $this->assertFalse($keyexists); } } /** * Test when try to logout, but required return is not set. */ public function test_user_logout_jwt_when_required_return_not_set() { $this->expectException(moodle_exception::class); $this->expectExceptionMessage('A required parameter (return) was missing'); $this->auth->user_logout_jwt(); } /** * Test when try to logout, but user is not logged in. */ public function test_user_logout_jwt_when_user_is_not_logged_in() { $_POST['return'] = self::REDIRECTION_PATH; $this->expectException(moodle_exception::class); $this->expectExceptionMessage( sprintf("Unsupported redirect to %s detected, execution terminated.", self::REDIRECTION_PATH) ); $this->auth->user_logout_jwt(); } /** * Test when try to logout, but user logged in with different auth type. */ public function test_user_logout_jwt_when_user_logged_in_with_different_auth() { global $USER; $_POST['return'] = self::REDIRECTION_PATH; $this->setUser($this->user); try { $this->auth->user_logout_jwt(); } catch (moodle_exception $e) { $this->assertTrue(isloggedin()); $this->assertEquals($USER->id, $this->user->id); $this->assertEquals( 'Incorrect logout request', $e->getMessage() ); } } /** * Test when try to logout, but user logged in with different auth type. */ public function test_user_logout_jwt_when_user_logged_in_but_return_not_set() { $this->setUser($this->user); $this->expectException(moodle_exception::class); $this->expectExceptionMessage('A required parameter (return) was missing'); $this->auth->user_logout_jwt(); } /** * Test successful logout. */ public function test_user_logout_jwt_logging_out() { global $USER; $this->setUser($this->user); $USER->auth = 'jwt'; $_POST['return'] = self::REDIRECTION_PATH; try { $this->auth->user_logout_jwt(); } catch (moodle_exception $e) { $this->assertFalse(isloggedin()); $this->assertEquals( sprintf('Unsupported redirect to %s detected, execution terminated.', self::REDIRECTION_PATH), $e->getMessage() ); } } }