weekly release 2.2dev
[moodle.git] / login / token.php
CommitLineData
13ea96c4
DC
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Return token
19 * @package moodlecore
20 * @copyright 2011 Dongsheng Cai <dongsheng@moodle.com>
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 */
23
24define('AJAX_SCRIPT', true);
25define('NO_MOODLE_COOKIES', true);
26
27require_once(dirname(dirname(__FILE__)) . '/config.php');
28
9b9d7a60 29$username = required_param('username', PARAM_USERNAME);
13ea96c4 30$password = required_param('password', PARAM_RAW);
5b9735b9 31$serviceshortname = required_param('service', PARAM_ALPHANUMEXT);
13ea96c4
DC
32
33echo $OUTPUT->header();
34
35if (!$CFG->enablewebservices) {
36 throw new moodle_exception('enablewsdescription', 'webservice');
37}
38$username = trim(moodle_strtolower($username));
39if (is_restored_user($username)) {
40 throw new moodle_exception('restoredaccountresetpassword', 'webservice');
41}
42$user = authenticate_user_login($username, $password);
43if (!empty($user)) {
44 if (isguestuser($user)) {
45 throw new moodle_exception('noguest');
46 }
47 if (empty($user->confirmed)) {
48 throw new moodle_exception('usernotconfirmed', 'moodle', '', $user->username);
49 }
50 // check credential expiry
51 $userauth = get_auth_plugin($user->auth);
52 if (!empty($userauth->config->expiration) and $userauth->config->expiration == 1) {
53 $days2expire = $userauth->password_expire($user->username);
54 if (intval($days2expire) < 0 ) {
55 throw new moodle_exception('passwordisexpired', 'webservice');
56 }
57 }
58
e922fe23
PS
59 // let enrol plugins deal with new enrolments if necessary
60 enrol_check_plugins($user);
61
13ea96c4
DC
62 // setup user session to check capability
63 session_set_user($user);
64
5b9735b9
JM
65 //check if the service exists and is enabled
66 $service = $DB->get_record('external_services', array('shortname' => $serviceshortname, 'enabled' => 1));
67 if (empty($service)) {
68 // will throw exception if no token found
69 throw new moodle_exception('servicenotavailable', 'webservice');
70 }
71
72 //check if there is any required system capability
73 if ($service->requiredcapability and !has_capability($service->requiredcapability, get_context_instance(CONTEXT_SYSTEM), $user)) {
74 throw new moodle_exception('missingrequiredcapability', 'webservice', '', $service->requiredcapability);
75 }
76
77 //specific checks related to user restricted service
78 if ($service->restrictedusers) {
79 $authoriseduser = $DB->get_record('external_services_users',
80 array('externalserviceid' => $service->id, 'userid' => $user->id));
81
82 if (empty($authoriseduser)) {
83 throw new moodle_exception('usernotallowed', 'webservice', '', $serviceshortname);
84 }
85
86 if (!empty($authoriseduser->validuntil) and $authoriseduser->validuntil < time()) {
87 throw new moodle_exception('invalidtimedtoken', 'webservice');
88 }
89
90 if (!empty($authoriseduser->iprestriction) and !address_in_subnet(getremoteaddr(), $authoriseduser->iprestriction)) {
91 throw new moodle_exception('invalidiptoken', 'webservice');
92 }
93 }
94
95 //Check if a token has already been created for this user and this service
96 //Note: this could be an admin created or an user created token.
97 // It does not really matter we take the first one that is valid.
98 $tokenssql = "SELECT t.id, t.sid, t.token, t.validuntil, t.iprestriction,
99 s.restrictedusers, s.id as serviceid, s.requiredcapability
13ea96c4
DC
100 FROM {external_tokens} t
101 JOIN {external_services} s
102 ON t.externalserviceid = s.id
103 WHERE s.shortname = ?
104 AND s.enabled = 1
105 AND t.userid = ?
13ea96c4 106 ORDER BY t.timecreated ASC";
5b9735b9
JM
107 $tokens = $DB->get_records_sql($tokenssql, array($serviceshortname, $user->id, time()));
108
109 //A bit of sanity checks
110 foreach ($tokens as $key=>$token) {
111
112 /// Checks related to a specific token. (script execution continue)
113 $unsettoken = false;
114 //if sid is set then there must be a valid associated session no matter the token type
115 if (!empty($token->sid)) {
116 $session = session_get_instance();
117 if (!$session->session_exists($token->sid)){
118 //this token will never be valid anymore, delete it
119 $DB->delete_records('external_tokens', array('sid'=>$token->sid));
120 $unsettoken = true;
121 }
122 }
123
124 //remove token if no valid anymore
125 //Also delete this wrong token (similar logic to the web service servers
126 // /webservice/lib.php/webservice_server::authenticate_by_token())
127 if (!empty($token->validuntil) and $token->validuntil < time()) {
128 $DB->delete_records('external_tokens', array('token'=>$token->token, 'tokentype'=> EXTERNAL_TOKEN_PERMANENT));
129 $unsettoken = true;
130 }
131
13ea96c4 132 // remove token if its ip not in whitelist
5b9735b9
JM
133 if (isset($token->iprestriction) and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
134 $unsettoken = true;
135 }
136
137 if ($unsettoken) {
13ea96c4
DC
138 unset($tokens[$key]);
139 }
140 }
5b9735b9
JM
141
142 // if some valid tokens exist then use the most recent
13ea96c4
DC
143 if (count($tokens) > 0) {
144 $token = array_pop($tokens);
145 } else {
5b9735b9
JM
146 if ( ($serviceshortname == MOODLE_OFFICIAL_MOBILE_SERVICE and has_capability('moodle/webservice:createmobiletoken', get_system_context()))
147 //Note: automatically token generation is not available to admin (they must create a token manually)
148 or (!is_siteadmin($user) && has_capability('moodle/webservice:createtoken', get_system_context()))) {
149 // if service doesn't exist, dml will throw exception
150 $service_record = $DB->get_record('external_services', array('shortname'=>$serviceshortname, 'enabled'=>1), '*', MUST_EXIST);
151 // create a new token
152 $token = new stdClass;
153 $token->token = md5(uniqid(rand(), 1));
154 $token->userid = $user->id;
155 $token->tokentype = EXTERNAL_TOKEN_PERMANENT;
156 $token->contextid = get_context_instance(CONTEXT_SYSTEM)->id;
157 $token->creatorid = $user->id;
158 $token->timecreated = time();
159 $token->externalserviceid = $service_record->id;
160 $tokenid = $DB->insert_record('external_tokens', $token);
161 add_to_log(SITEID, 'webservice', get_string('createtokenforuserauto', 'webservice'), '' , 'User ID: ' . $user->id);
162 $token->id = $tokenid;
163 } else {
164 throw new moodle_exception('cannotcreatetoken', 'webservice', '', $serviceshortname);
13ea96c4
DC
165 }
166 }
167
168 // log token access
169 $DB->set_field('external_tokens', 'lastaccess', time(), array('id'=>$token->id));
170
13ea96c4 171 add_to_log(SITEID, 'webservice', 'user request webservice token', '' , 'User ID: ' . $user->id);
d8f85b6e
SH
172
173 $usertoken = new stdClass;
13ea96c4
DC
174 $usertoken->token = $token->token;
175 echo json_encode($usertoken);
176} else {
177 throw new moodle_exception('usernamenotfound', 'moodle');
9b9d7a60 178}