| 1 | efrain | 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 |  * This file responds to a login authentication request
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @package    mod_lti
 | 
        
           |  |  | 21 |  * @copyright  2019 Stephen Vickers
 | 
        
           |  |  | 22 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 23 |  */
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | require_once(__DIR__ . '/../../config.php');
 | 
        
           |  |  | 26 | require_once($CFG->dirroot . '/mod/lti/locallib.php');
 | 
        
           |  |  | 27 | global $_POST, $_SERVER;
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 | if (!isloggedin() && empty($_POST['repost'])) {
 | 
        
           |  |  | 30 |     header_remove("Set-Cookie");
 | 
        
           |  |  | 31 |     $PAGE->set_pagelayout('popup');
 | 
        
           |  |  | 32 |     $PAGE->set_context(context_system::instance());
 | 
        
           |  |  | 33 |     $output = $PAGE->get_renderer('mod_lti');
 | 
        
           |  |  | 34 |     $page = new \mod_lti\output\repost_crosssite_page($_SERVER['REQUEST_URI'], $_POST);
 | 
        
           |  |  | 35 |     echo $output->header();
 | 
        
           |  |  | 36 |     echo $output->render($page);
 | 
        
           |  |  | 37 |     echo $output->footer();
 | 
        
           |  |  | 38 |     return;
 | 
        
           |  |  | 39 | }
 | 
        
           |  |  | 40 |   | 
        
           |  |  | 41 | $scope = optional_param('scope', '', PARAM_TEXT);
 | 
        
           |  |  | 42 | $responsetype = optional_param('response_type', '', PARAM_TEXT);
 | 
        
           |  |  | 43 | $clientid = optional_param('client_id', '', PARAM_TEXT);
 | 
        
           |  |  | 44 | $redirecturi = optional_param('redirect_uri', '', PARAM_URL);
 | 
        
           |  |  | 45 | $loginhint = optional_param('login_hint', '', PARAM_TEXT);
 | 
        
           |  |  | 46 | $ltimessagehintenc = optional_param('lti_message_hint', '', PARAM_TEXT);
 | 
        
           |  |  | 47 | $state = optional_param('state', '', PARAM_TEXT);
 | 
        
           |  |  | 48 | $responsemode = optional_param('response_mode', '', PARAM_TEXT);
 | 
        
           |  |  | 49 | $nonce = optional_param('nonce', '', PARAM_TEXT);
 | 
        
           |  |  | 50 | $prompt = optional_param('prompt', '', PARAM_TEXT);
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 | $ok = !empty($scope) && !empty($responsetype) && !empty($clientid) &&
 | 
        
           |  |  | 53 |       !empty($redirecturi) && !empty($loginhint) &&
 | 
        
           |  |  | 54 |       !empty($nonce);
 | 
        
           |  |  | 55 |   | 
        
           |  |  | 56 | if (!$ok) {
 | 
        
           |  |  | 57 |     $error = 'invalid_request';
 | 
        
           |  |  | 58 | }
 | 
        
           |  |  | 59 | $ltimessagehint = json_decode($ltimessagehintenc);
 | 
        
           |  |  | 60 | $ok = $ok && isset($ltimessagehint->launchid);
 | 
        
           |  |  | 61 | if (!$ok) {
 | 
        
           |  |  | 62 |     $error = 'invalid_request';
 | 
        
           |  |  | 63 |     $desc = 'No launch id in LTI hint';
 | 
        
           |  |  | 64 | }
 | 
        
           |  |  | 65 | if ($ok && ($scope !== 'openid')) {
 | 
        
           |  |  | 66 |     $ok = false;
 | 
        
           |  |  | 67 |     $error = 'invalid_scope';
 | 
        
           |  |  | 68 | }
 | 
        
           |  |  | 69 | if ($ok && ($responsetype !== 'id_token')) {
 | 
        
           |  |  | 70 |     $ok = false;
 | 
        
           |  |  | 71 |     $error = 'unsupported_response_type';
 | 
        
           |  |  | 72 | }
 | 
        
           |  |  | 73 | if ($ok) {
 | 
        
           |  |  | 74 |     $launchid = $ltimessagehint->launchid;
 | 
        
           |  |  | 75 |     list($courseid, $typeid, $id, $messagetype, $foruserid, $titleb64, $textb64) = explode(',', $SESSION->$launchid, 7);
 | 
        
           |  |  | 76 |     unset($SESSION->$launchid);
 | 
        
           |  |  | 77 |     $config = lti_get_type_type_config($typeid);
 | 
        
           |  |  | 78 |     $ok = ($clientid === $config->lti_clientid);
 | 
        
           |  |  | 79 |     if (!$ok) {
 | 
        
           |  |  | 80 |         $error = 'unauthorized_client';
 | 
        
           |  |  | 81 |     }
 | 
        
           |  |  | 82 | }
 | 
        
           |  |  | 83 | if ($ok && ($loginhint !== $USER->id)) {
 | 
        
           |  |  | 84 |     $ok = false;
 | 
        
           |  |  | 85 |     $error = 'access_denied';
 | 
        
           |  |  | 86 | }
 | 
        
           |  |  | 87 |   | 
        
           |  |  | 88 | // If we're unable to load up config; we cannot trust the redirect uri for POSTing to.
 | 
        
           |  |  | 89 | if (empty($config)) {
 | 
        
           |  |  | 90 |     throw new moodle_exception('invalidrequest', 'error');
 | 
        
           |  |  | 91 | } else {
 | 
        
           |  |  | 92 |     $uris = array_map("trim", explode("\n", $config->lti_redirectionuris));
 | 
        
           |  |  | 93 |     if (!in_array($redirecturi, $uris)) {
 | 
        
           |  |  | 94 |         throw new moodle_exception('invalidrequest', 'error');
 | 
        
           |  |  | 95 |     }
 | 
        
           |  |  | 96 | }
 | 
        
           |  |  | 97 | if ($ok) {
 | 
        
           |  |  | 98 |     if (isset($responsemode)) {
 | 
        
           |  |  | 99 |         $ok = ($responsemode === 'form_post');
 | 
        
           |  |  | 100 |         if (!$ok) {
 | 
        
           |  |  | 101 |             $error = 'invalid_request';
 | 
        
           |  |  | 102 |             $desc = 'Invalid response_mode';
 | 
        
           |  |  | 103 |         }
 | 
        
           |  |  | 104 |     } else {
 | 
        
           |  |  | 105 |         $ok = false;
 | 
        
           |  |  | 106 |         $error = 'invalid_request';
 | 
        
           |  |  | 107 |         $desc = 'Missing response_mode';
 | 
        
           |  |  | 108 |     }
 | 
        
           |  |  | 109 | }
 | 
        
           |  |  | 110 | if ($ok && !empty($prompt) && ($prompt !== 'none')) {
 | 
        
           |  |  | 111 |     $ok = false;
 | 
        
           |  |  | 112 |     $error = 'invalid_request';
 | 
        
           |  |  | 113 |     $desc = 'Invalid prompt';
 | 
        
           |  |  | 114 | }
 | 
        
           |  |  | 115 |   | 
        
           |  |  | 116 | if ($ok) {
 | 
        
           |  |  | 117 |     $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
 | 
        
           |  |  | 118 |     if ($id) {
 | 
        
           |  |  | 119 |         $cm = get_coursemodule_from_id('lti', $id, 0, false, MUST_EXIST);
 | 
        
           |  |  | 120 |         $context = context_module::instance($cm->id);
 | 
        
           |  |  | 121 |         require_login($course, true, $cm);
 | 
        
           |  |  | 122 |         require_capability('mod/lti:view', $context);
 | 
        
           |  |  | 123 |         $lti = $DB->get_record('lti', array('id' => $cm->instance), '*', MUST_EXIST);
 | 
        
           |  |  | 124 |         $lti->cmid = $cm->id;
 | 
        
           |  |  | 125 |         list($endpoint, $params) = lti_get_launch_data($lti, $nonce, $messagetype, $foruserid);
 | 
        
           |  |  | 126 |     } else {
 | 
        
           |  |  | 127 |         require_login($course);
 | 
        
           |  |  | 128 |         $context = context_course::instance($courseid);
 | 
        
           |  |  | 129 |         require_capability('moodle/course:manageactivities', $context);
 | 
        
           |  |  | 130 |         require_capability('mod/lti:addcoursetool', $context);
 | 
        
           |  |  | 131 |         // Set the return URL. We send the launch container along to help us avoid frames-within-frames when the user returns.
 | 
        
           |  |  | 132 |         $returnurlparams = [
 | 
        
           |  |  | 133 |             'course' => $courseid,
 | 
        
           |  |  | 134 |             'id' => $typeid,
 | 
        
           |  |  | 135 |             'sesskey' => sesskey()
 | 
        
           |  |  | 136 |         ];
 | 
        
           |  |  | 137 |         $returnurl = new \moodle_url('/mod/lti/contentitem_return.php', $returnurlparams);
 | 
        
           |  |  | 138 |         // Prepare the request.
 | 
        
           |  |  | 139 |         $title = base64_decode($titleb64);
 | 
        
           |  |  | 140 |         $text = base64_decode($textb64);
 | 
        
           |  |  | 141 |         $request = lti_build_content_item_selection_request($typeid, $course, $returnurl, $title, $text,
 | 
        
           |  |  | 142 |                                                             [], [], false, true, false, false, false, $nonce);
 | 
        
           |  |  | 143 |         $endpoint = $request->url;
 | 
        
           |  |  | 144 |         $params = $request->params;
 | 
        
           |  |  | 145 |     }
 | 
        
           |  |  | 146 | } else {
 | 
        
           |  |  | 147 |     $params['error'] = $error;
 | 
        
           |  |  | 148 |     if (!empty($desc)) {
 | 
        
           |  |  | 149 |         $params['error_description'] = $desc;
 | 
        
           |  |  | 150 |     }
 | 
        
           |  |  | 151 | }
 | 
        
           |  |  | 152 | if (isset($state)) {
 | 
        
           |  |  | 153 |     $params['state'] = $state;
 | 
        
           |  |  | 154 | }
 | 
        
           |  |  | 155 | unset($SESSION->lti_message_hint);
 | 
        
           |  |  | 156 | $r = '<form action="' . $redirecturi . "\" name=\"ltiAuthForm\" id=\"ltiAuthForm\" " .
 | 
        
           |  |  | 157 |      "method=\"post\" enctype=\"application/x-www-form-urlencoded\">\n";
 | 
        
           |  |  | 158 | if (!empty($params)) {
 | 
        
           |  |  | 159 |     foreach ($params as $key => $value) {
 | 
        
           |  |  | 160 |         $key = htmlspecialchars($key, ENT_COMPAT);
 | 
        
           |  |  | 161 |         $value = htmlspecialchars($value, ENT_COMPAT);
 | 
        
           |  |  | 162 |         $r .= "  <input type=\"hidden\" name=\"{$key}\" value=\"{$value}\"/>\n";
 | 
        
           |  |  | 163 |     }
 | 
        
           |  |  | 164 | }
 | 
        
           |  |  | 165 | $r .= "</form>\n";
 | 
        
           |  |  | 166 | $r .= "<script type=\"text/javascript\">\n" .
 | 
        
           |  |  | 167 |     "//<![CDATA[\n" .
 | 
        
           |  |  | 168 |     "document.ltiAuthForm.submit();\n" .
 | 
        
           |  |  | 169 |     "//]]>\n" .
 | 
        
           |  |  | 170 |     "</script>\n";
 | 
        
           |  |  | 171 | echo $r;
 |