Merge branch 'MDL-41810_master' of https://github.com/totara/openbadges
[moodle.git] / badges / backpackconnect.php
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/>.
17 /**
18  * AJAX script for validating backpack connection.
19  *
20  * @package    core
21  * @subpackage badges
22  * @copyright  2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  * @author     Simon Coggins <simon.coggins@totaralms.com>
25  */
27 define('AJAX_SCRIPT', true);
29 require_once(dirname(dirname(__FILE__)) . '/config.php');
30 require_once($CFG->dirroot . '/badges/lib/backpacklib.php');
31 require_once($CFG->libdir . '/filelib.php');
32 require_once($CFG->libdir . '/badgeslib.php');
34 require_sesskey();
35 require_login();
36 $PAGE->set_url('/badges/backpackconnect.php');
37 $PAGE->set_context(context_system::instance());
38 echo $OUTPUT->header();
40 // Use PHP input filtering as there is no PARAM type for
41 // the type of cleaning that is required (ASCII chars 32-127 only).
42 $assertion = filter_input(
43     INPUT_POST,
44     'assertion',
45     FILTER_UNSAFE_RAW,
46     FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH
47 );
49 // Audience is the site url scheme + host + port only.
50 $wwwparts = parse_url($CFG->wwwroot);
51 $audience = $wwwparts['scheme'] . '://' . $wwwparts['host'];
52 $audience .= isset($wwwparts['port']) ? $wwwparts['port'] : '';
53 $params = 'assertion=' . urlencode($assertion) . '&audience=' .
54            urlencode($audience);
56 $curl = new curl();
57 $url = 'https://verifier.login.persona.org/verify';
58 $options = array(
59     'FRESH_CONNECT'  => true,
60     'RETURNTRANSFER' => true,
61     'FORBID_REUSE'   => true,
62     'SSL_VERIFYPEER' => true,
63     'SSL_VERIFYHOST' => 2,
64     'HEADER'         => 0,
65     'HTTPHEADER'     => array('Content-type: application/x-www-form-urlencoded'),
66     'CONNECTTIMEOUT' => 0,
67     'TIMEOUT' => 10, // Fail if data not returned within 10 seconds.
68 );
69 $result = $curl->post($url, $params, $options);
71 // Handle time-out and failed request.
72 if ($curl->errno != 0) {
73     if ($curl->errno == CURLE_OPERATION_TIMEOUTED) {
74         $reason = get_string('error:requesttimeout', 'badges');
75     } else {
76         $reason = get_string('error:requesterror', 'badges', $curl->errno);
77     }
78     badges_send_response('failure', $reason);
79 }
81 $data = json_decode($result);
83 if (!isset($data->status) || $data->status != 'okay') {
84     $reason = isset($data->reason) ? $data->reason : get_string('error:connectionunknownreason', 'badges');
85     badges_send_response('failure', $reason);
86 }
88 // Make sure email matches a backpack.
89 $check = new stdClass();
90 $check->backpackurl = 'http://' . BADGE_BACKPACKURL;
91 $check->email = $data->email;
93 $bp = new OpenBadgesBackpackHandler($check);
94 $request = $bp->curl_request('user');
95 if (isset($request->status) && $request->status == 'missing') {
96     $reason = get_string('error:backpackemailnotfound', 'badges', $data->email);
97     badges_send_response('failure', $reason);
98 } else if (empty($request->userId)) {
99     $reason = get_string('error:backpackdatainvalid', 'badges');
100     badges_send_response('failure', $reason);
101 } else {
102     $backpackuid = $request->userId;
105 // Insert record.
106 $obj = new stdClass();
107 $obj->userid = $USER->id;
108 $obj->email = $data->email;
109 $obj->backpackurl = 'http://' . BADGE_BACKPACKURL;
110 $obj->backpackuid = $backpackuid;
111 $obj->autosync = 0;
112 $obj->password = '';
113 $DB->insert_record('badge_backpack', $obj);
115 // Return success indicator and email address.
116 badges_send_response('success', $data->email);
119 /**
120  * Return a JSON response containing the response provided.
121  *
122  * @param string $status Status of the response, typically 'success' or 'failure'.
123  * @param string $responsetext On success, the email address of the user,
124  *                             otherwise a reason for the failure.
125  * @return void Outputs the JSON and terminates the script.
126  */
127 function badges_send_response($status, $responsetext) {
128     $out = new stdClass();
129     $out->status = $status;
130     if ($status == 'success') {
131         $out->email = $responsetext;
132     } else {
133         $out->reason = $responsetext;
134         send_header_404();
135     }
136     echo json_encode($out);
137     exit;