public function test_login_failed() { // The Web service API doesn't allow the testing of the events directly by // calling some functions which trigger the events, so what we are going here // is just checking that the event returns the expected information. $sink = $this->redirectEvents(); $fakelogdata = array(1, 'B', true, null); $params = array('other' => array('reason' => 'Unit Test', 'method' => 'Some method', 'tokenid' => '123')); $event = \core\event\webservice_login_failed::create($params); $event->set_legacy_logdata($fakelogdata); $event->trigger(); $events = $sink->get_events(); $this->assertCount(1, $events); $event = reset($events); $this->assertEquals(context_system::instance(), $event->get_context()); $this->assertEquals($params['other']['reason'], $event->other['reason']); $this->assertEquals($params['other']['method'], $event->other['method']); $this->assertEquals($params['other']['tokenid'], $event->other['tokenid']); $this->assertEventLegacyLogData($fakelogdata, $event); // We cannot set the token in the other properties. $params['other']['token'] = 'I should not be set'; try { $event = \core\event\webservice_login_failed::create($params); $this->fail('The token cannot be allowed in \\core\\event\\webservice_login_failed'); } catch (coding_exception $e) { } }
/** * User authentication by token * * @param string $tokentype token type (EXTERNAL_TOKEN_EMBEDDED or EXTERNAL_TOKEN_PERMANENT) * @return stdClass the authenticated user * @throws webservice_access_exception */ protected function authenticate_by_token($tokentype) { global $DB; $loginfaileddefaultparams = array('context' => context_system::instance(), 'other' => array('method' => $this->authmethod, 'reason' => null)); if (!($token = $DB->get_record('external_tokens', array('token' => $this->token, 'tokentype' => $tokentype)))) { // Log failed login attempts. $params = $loginfaileddefaultparams; $params['other']['reason'] = 'invalid_token'; $event = \core\event\webservice_login_failed::create($params); $event->set_legacy_logdata(array(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . $this->token . " - " . getremoteaddr(), 0)); $event->trigger(); throw new moodle_exception('invalidtoken', 'webservice'); } if ($token->validuntil and $token->validuntil < time()) { $DB->delete_records('external_tokens', array('token' => $this->token, 'tokentype' => $tokentype)); throw new webservice_access_exception('Invalid token - token expired - check validuntil time for the token'); } if ($token->sid) { //assumes that if sid is set then there must be a valid associated session no matter the token type if (!\core\session\manager::session_exists($token->sid)) { $DB->delete_records('external_tokens', array('sid' => $token->sid)); throw new webservice_access_exception('Invalid session based token - session not found or expired'); } } if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) { $params = $loginfaileddefaultparams; $params['other']['reason'] = 'ip_restricted'; $params['other']['tokenid'] = $token->id; $event = \core\event\webservice_login_failed::create($params); $event->add_record_snapshot('external_tokens', $token); $event->set_legacy_logdata(array(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . getremoteaddr(), 0)); $event->trigger(); throw new webservice_access_exception('Invalid service - IP:' . getremoteaddr() . ' is not supported - check this allowed user'); } $this->restricted_context = context::instance_by_id($token->contextid); $this->restricted_serviceid = $token->externalserviceid; $user = $DB->get_record('user', array('id' => $token->userid), '*', MUST_EXIST); // log token access $DB->set_field('external_tokens', 'lastaccess', time(), array('id' => $token->id)); return $user; }