import
[web.mtrack] / web / openid.php
1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
3 include '../inc/common.php';
4 require_once 'Auth/OpenID/Consumer.php';
5 require_once 'Auth/OpenID/FileStore.php';
6 require_once 'Auth/OpenID/SReg.php';
7 require_once 'Auth/OpenID/PAPE.php';
8
9 $store_location = MTrackConfig::get('openid', 'store_dir');
10 if (!$store_location) {
11   $store_location = MTrackConfig::get('core', 'vardir') . '/openid';
12 }
13 if (!is_dir($store_location)) {
14   mkdir($store_location);
15 }
16 $store = new Auth_OpenID_FileStore($store_location);
17 $consumer = new Auth_OpenID_Consumer($store);
18
19 $message = null;
20
21 $pi = mtrack_get_pathinfo();
22 if ($_SERVER['REQUEST_METHOD'] == 'POST' && $pi != 'register') {
23
24   $req = null;
25
26   if (!isset($_POST['openid_identifier']) ||
27       !strlen($_POST['openid_identifier'])) {
28     $message = "you must fill in your OpenID";
29   } else {
30     $id = $_POST['openid_identifier'];
31     if (!preg_match('/^https?:\/\//', $id)) {
32       $id = "http://$id";
33     }
34     $req = $consumer->begin($id);
35     if (!$req) {
36       $message = "not a valid OpenID";
37     }
38   }
39   if ($req) {
40     $sreg = Auth_OpenID_SRegRequest::build(
41       array('nickname', 'fullname', 'email')
42     );
43     $req->addExtension($sreg);
44
45     if ($req->shouldSendRedirect()) {
46       $rurl = $req->redirectURL(
47         $ABSWEB, $ABSWEB . 'openid.php/callback');
48       if (Auth_OpenID::isFailure($rurl)) {
49         $message = "Unable to redirect to server: " . $rurl->message;
50       } else {
51         header("Location: $rurl");
52         exit;
53       }
54     } else {
55       $html = $req->htmlMarkup($ABSWEB, $ABSWEB . 'openid.php/callback',
56         false, array('id' => 'openid_message'));
57       if (Auth_OpenID::isFailure($html)) {
58         $message = "Unable to redirect to server: " . $html->message;
59       } else {
60         echo $html;
61       }
62     }
63   }
64 } else if ($pi == 'callback') {
65   $res = $consumer->complete($ABSWEB . 'openid.php/callback');
66
67   if ($res->status == Auth_OpenID_CANCEL) {
68     $message = 'Verification cancelled';
69   } else if ($res->status == Auth_OpenID_FAILURE) {
70     $message = 'OpenID authentication failed: ' . $res->message;
71   } else if ($res->status == Auth_OpenID_SUCCESS) {
72     $id = $res->getDisplayIdentifier();
73     $sreg = Auth_OpenID_SRegResponse::fromSuccessResponse($res)->contents();
74
75     if (!empty($sreg['nickname'])) {
76       $name = $sreg['nickname'];
77     } else if (!empty($sreg['fullname'])) {
78       $name = $sreg['fullname'];
79     } else {
80       $name = $id;
81     }
82     $message = 'Authenticated as ' . $name;
83
84     $_SESSION['openid.id'] = $id;
85     unset($_SESSION['openid.userid']);
86     $_SESSION['openid.name'] = $name;
87     if (!empty($sreg['email'])) {
88       $_SESSION['openid.email'] = $sreg['email'];
89     }
90     /* See if we can find a canonical identity for the user */
91     foreach (MTrackDB::q('select userid from useraliases where alias = ?',
92         $id)->fetchAll() as $row) {
93       $_SESSION['openid.userid'] = $row[0];
94       break;
95     }
96
97     if (!isset($_SESSION['openid.userid'])) {
98       /* no alias; is there a direct userinfo entry? */
99       foreach (MTrackDB::q('select userid from userinfo where userid = ?',
100           $id)->fetchAll() as $row) {
101         $_SERVER['openid.userid'] = $row[0];
102         break;
103       }
104     }
105
106     if (!isset($_SESSION['openid.userid'])) {
107       /* prompt the user to fill out some basic details so that we can create
108        * a local identity and associate their OpenID with it */
109       header("Location: {$ABSWEB}openid.php/register?" .
110         http_build_query($sreg));
111     } else {
112       header("Location: " . $ABSWEB);
113     }
114     exit;
115   } else {
116     $message = 'An error occurred while talking to your OpenID provider';
117   }
118 } else if ($pi == 'signout') {
119   session_destroy();
120   header('Location: ' . $ABSWEB);
121   exit;
122 } else if ($pi == 'register') {
123
124   if (!isset($_SESSION['openid.id'])) {
125     header("Location: " . $ABSWEB);
126     exit;
127   }
128
129   $userid = isset($_REQUEST['nickname']) ? $_REQUEST['nickname'] : '';
130   $email = isset($_REQUEST['email']) ? $_REQUEST['email'] : '';
131   $message = null;
132
133   /* See if we can find a canonical identity for the user */
134   foreach (MTrackDB::q('select userid from useraliases where alias = ?',
135       $_SESSION['openid.id'])->fetchAll() as $row) {
136     header("Location: " . $ABSWEB);
137     exit;
138   }
139
140   if ($_SERVER['REQUEST_METHOD'] == 'POST') {
141     if (!strlen($userid)) {
142       $message = 'You must enter a userid';
143     } else {
144       /* is the requested id available? */
145       $avail = true;
146       foreach (MTrackDB::q('select userid from userinfo where userid = ?',
147             $userid)->fetchAll() as $row) {
148         $avail = false;
149         $message = "Your selected user ID is not available";
150       }
151       if ($avail) {
152         MTrackDB::q('insert into userinfo (userid, email, active) values (?, ?, 1)', $userid, $email);
153         /* we know the alias doesn't already exist, because we double-checked
154          * for it above */
155         MTrackDB::q('insert into useraliases (userid, alias) values (?,?)',
156           $userid, $_SESSION['openid.id']);
157         header("Location: {$ABSWEB}user.php?user=$userid&edit=1");
158         exit;
159       }
160     }
161   }
162
163   mtrack_head('Register');
164
165   $userid = htmlentities($userid, ENT_QUOTES, 'utf-8');
166   $email = htmlentities($email, ENT_QUOTES, 'utf-8');
167
168   if ($message) {
169     $message = htmlentities($message, ENT_QUOTES, 'utf-8');
170     echo <<<HTML
171 <div class='ui-state-error ui-corner-all'>
172     <span class='ui-icon ui-icon-alert'></span>
173     $message
174 </div>
175 HTML;
176   }
177
178   echo <<<HTML
179 <h1>Set up your local account</h1>
180 <form method='post'>
181   User ID: <input type='text' name='nickname' value='$userid'><br>
182   Email: <input type='text' name='email' value='$email'><br>
183   <button type='submit'>Save</button>
184 </form>
185
186
187 HTML;
188   mtrack_foot();
189   exit;
190 }
191
192 mtrack_head('Authentication Required');
193 echo "<h1>Please sign in with your <a id='openidlink' href='http://openid.net'><img src='{$ABSWEB}images/logo_openid.png' alt='OpenID' border='0'></a></h1>\n";
194 echo "<form method='post' action='{$ABSWEB}openid.php'>";
195 echo "<input type='text' name='openid_identifier' id='openid_identifier'>";
196 echo " <button type='submit' id='openid-sign-in'>Sign In</button>";
197
198 if ($message) {
199   $message = htmlentities($message, ENT_QUOTES, 'utf-8');
200   echo <<<HTML
201 <div class='ui-state-highlight ui-corner-all'>
202     <span class='ui-icon ui-icon-info'></span>
203     $message
204 </div>
205 HTML;
206 }
207
208 echo "</form>";
209
210
211 mtrack_foot();
212