· 8 years ago · Apr 14, 2018, 04:38 AM
1ini_set('include_path', ini_get('include_path').PATH_SEPARATOR.dirname(__FILE__));
2
3require_once "Auth/OpenID/Consumer.php";
4require_once "Auth/OpenID/MySQLStore.php";
5require_once "Auth/OpenID/SReg.php";
6
7class openidauth
8{
9 public static function install(&$conf, $old_conf)
10 {
11 global $options;
12
13 $conf['version'] = 1; // keep track of version for SQL changes, etc...
14
15 Hook::add_callback('unlog:page_act:openid_login', 'openidauth', 'login');
16 Hook::add_callback('unlog:page_act:openid_login_return', 'openidauth', 'login_return');
17 Hook::add_callback('unlog:page_act:openid_createuser', 'openidauth', 'createuser');
18 Hook::add_callback('unlog:page_act:openid_createuser_return', 'openidauth', 'createuser_return');
19
20 Hook::add_callback('unlog:page_act:createuser', 'openidauth', 'createuser_finish');
21 Hook::add_callback('createuser:success', 'openidauth', 'createuser_success');
22
23 Hook::add_callback('login_functions:call_login', 'openidauth', 'call_login');
24
25 if (!isset($old_conf['version'])) // pre-version version needs to be replaced
26 {
27 $del_copy = Plugin::do_queries(
28 array('Renaming old table' =>
29 'RENAME TABLE openid_to_userid TO tmp_oid_to_uid'
30 ));
31 }
32 else $del_copy = false;
33
34 echo "\n";
35 $q1 = Plugin::do_queries(
36 array(
37 'Creating openid_to_userid table' =>
38 'CREATE TABLE IF NOT EXISTS openid_to_userid'.'('.
39 'openid_to_userid_id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (openid_to_userid_id),'.
40 'user_id INT NOT NULL, INDEX(user_id),'.
41 'openid VARCHAR(2048) NOT NULL, INDEX(openid(32))'.
42 ')'));
43
44 $del_copy = $del_copy && Plugin::do_queries(
45 array('Copying old data to new table' =>
46 'INSERT openid_to_userid (user_id, openid) SELECT user_id, openid FROM tmp_oid_to_uid',
47 'Deleting old table' =>
48 'DROP TABLE IF EXISTS tmp_oid_to_uid',
49 ));
50
51 echo "Creating OpenID tables\n";
52 $db = DB::connect($options['database']);
53 $store = new Auth_OpenID_MySQLStore($db);
54 $q2 = $store->createTables();
55 if(!$q2) echo "OpenID tables not created! They probably already exist.\n";
56 else echo "..success\n";
57 return $q1 && $q2;
58 }
59
60 private static function &getConsumer()
61 {
62 global $options;
63
64 $db = DB::connect($options['database']);
65 $store = new Auth_OpenID_MySQLStore($db);
66 return new Auth_OpenID_Consumer($store);
67 }
68
69 static function call_login($param, &$smarty, &$message)
70 {
71 if (isset($_COOKIE['remember_openid']) && $_COOKIE['remember_openid'] != '')
72 {
73 $smarty->assign('openid_identifier', $_COOKIE['remember_openid']);
74 $smarty->assign('openid_mode', true);
75 $smarty->assign('remember_openid', 'checked');
76 }
77 return array('ok', true);
78 }
79
80 static function getScheme() {
81 $scheme = 'http';
82 if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') {
83 $scheme .= 's';
84 }
85 return $scheme;
86 }
87
88 static function getReturnTo($act) {
89 return sprintf("%s://%s/unlog.php?page_act=$act",
90 self::getScheme(), $_SERVER['SERVER_NAME']);
91 }
92
93 static function getTrustRoot() {
94 return sprintf("%s://%s/",
95 self::getScheme(), $_SERVER['SERVER_NAME']);
96 }
97
98 public static function login(&$smarty)
99 {
100 if (isset($_REQUEST['remember_openid']) && $_REQUEST['remember_openid'] == '1')
101 {
102 setcookie('remember_openid', $_REQUEST['openid_identifier'], time()+365*24*60*60);
103 }
104 else
105 {
106 setcookie('remember_openid', '', time()-60*60);
107 }
108
109 $ret = self::base_login('openid_login_return');
110 if (is_string($ret))
111 {
112 $smarty->assign('openid_mode', true);
113 call_login(1, $smarty, $ret);
114 }
115 return array('exit', $ret);
116 }
117
118 public static function login_return(&$smarty)
119 {
120 $result = self::base_login_return();
121 if (is_object($result))
122 {
123 $user_id = self::openid_exists($result->identity_url);
124 if ($user_id)
125 {
126 $user = DB_DataObject::factory('users');
127 $user->user_id = $user_id;
128 if ($user->find(true))
129 {
130 require_once('login_functions.php');
131 require_once('swl_crypt.php');
132 $crypter = new swlCrypt();
133 login($crypter->decrypt($user->email_address), null, $smarty,"",false, true);
134 return array('exit', 0);
135 }
136 }
137 return self::createuser_return($smarty, $result);
138 }
139 if (!is_string($result)) $result = "Error logging in.";
140
141
142 $smarty->assign('openid_mode', true);
143 call_login(1, $smarty, $result);
144 }
145
146 public static function createuser(&$smarty)
147 {
148 $ret = self::base_login('openid_createuser_return');
149 if (is_string($ret))
150 {
151 $smarty->assign('message', $ret);
152 $_REQUEST['page_act'] = 'newuser'; // show the createuser page
153 return array('skip');
154 }
155 return array('exit', $ret);
156 }
157
158 public static function createuser_return(&$smarty, $result = null)
159 {
160 if (!$result) $result = self::base_login_return();
161 if (is_object($result))
162 {
163 if (self::openid_exists($result->identity_url))
164 {
165 $_REQUEST['page_act'] = 'openid_login_return'; // they already have an account...log them in
166 return array('skip');
167 }
168
169 $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($result);
170 $sreg = $sreg_resp->contents();
171
172 if (isset($sreg['fullname'])) {
173 list($sreg['firstname'], $sreg['lastname']) = explode(' ', $sreg['fullname']);
174 }
175 $sreg['identifier'] = $result->identity_url;
176 $smarty->assign('openid', $sreg);
177 }
178 else
179 {
180 $smarty->assign('openid_mode', true);
181 $smarty->assign('message', $result);
182 }
183
184 $_REQUEST['page_act'] = 'newuser'; // show the createuser page
185 return array('ok', true);
186 }
187
188 private static function openid_exists($openid)
189 {
190 $oid = DB_DataObject::factory('openid_to_userid');
191 $oid->openid = $openid;
192 if ($oid->find(true)) return $oid->user_id;
193 return false;
194 }
195
196 public static function createuser_finish(&$smarty)
197 {
198 if (isset($_REQUEST['openid_identifier']))
199 {
200 if (self::openid_exists($_REQUEST['openid_identifier']))
201 {
202 $_REQUEST['page_act'] = 'newuser'; // show the createuser page
203 $smarty->assign('openid_mode', true);
204 $smarty->assign('message', 'OpenID already in use!');
205 return array('skip');
206 }
207
208 $_REQUEST["passwd"] = $_REQUEST["passwd2"] = md5(rand());
209 return array('ok', true);
210 }
211 return array('skip');
212 }
213
214 public static function createuser_success($user_id)
215 {
216 $ret = self::associate_uid_oid($user_id, $_REQUEST['openid_identifier']);
217 if (is_string($ret))
218 {
219 // something went horribly wrong.
220 die($ret);
221 }
222 return array('ok', true);
223 }
224
225 public static function associate_uid_oid($user_id, $openid)
226 {
227 $oid = DB_DataObject::factory('openid_to_userid');
228 $oid->user_id = $user_id;
229 $oid->openid = $openid;
230 if ($oid->insert()) return true;
231
232 if (isset($oid->_lastError)) return "DB Error: ".$oid->_lastError;
233 return "Error connecting OpenID with user account.";
234 }
235
236 /**
237 * Do an openid login
238 * @param string $redir page to return to after login
239 * @returns int|string the number 0 on success, a string with an error on failure.
240 */
241 public static function base_login($redir)
242 {
243 $consumer = self::getConsumer();
244 $auth_request = @$consumer->begin($_REQUEST['openid_identifier']);
245
246 if (!$auth_request) {
247 return "Authentication error; not a valid OpenID.";
248 }
249
250 $sreg_request = Auth_OpenID_SRegRequest::build(
251 explode(',', Plugin::$config['openidauth']['required_fields']),
252 explode(',', Plugin::$config['openidauth']['optional_fields'])
253 );
254
255 if ($sreg_request) {
256 $auth_request->addExtension($sreg_request);
257 }
258
259 // Redirect the user to the OpenID server for authentication.
260 // Store the token for this authentication so we can verify the
261 // response.
262
263 // For OpenID 1, send a redirect. For OpenID 2, use a Javascript
264 // form to send a POST request to the server.
265 if ($auth_request->shouldSendRedirect()) {
266 $redirect_url = $auth_request->redirectURL(self::getTrustRoot(),
267 self::getReturnTo($redir));
268
269 // If the redirect URL can't be built, display an error
270 // message.
271 if (Auth_OpenID::isFailure($redirect_url)) {
272 return ("Could not redirect to server: " . $redirect_url->message);
273 } else {
274 // Send redirect.
275 header("Location: ".$redirect_url);
276 }
277 } else {
278 // Generate form markup and render it.
279 $form_id = 'openid_message';
280 $form_html = $auth_request->formMarkup(getTrustRoot(), getReturnTo(),
281 false, array('id' => $form_id));
282
283 // Display an error if the form markup couldn't be generated;
284 // otherwise, render the HTML.
285 if (Auth_OpenID::isFailure($form_html)) {
286 return ("Could not redirect to server: " . $form_html->message);
287 } else {
288 $page_contents = array(
289 "<html><head><title>",
290 "OpenID transaction in progress",
291 "</title></head>",
292 "<body onload='document.getElementById(\"".$form_id."\").submit()'>",
293 $form_html,
294 "</body></html>");
295
296 print implode("\n", $page_contents);
297 }
298 }
299 return 0;
300 }
301
302 /**
303 * Check the return from the openid server
304 * @returns object|string registration info if successful, error message if failed
305 */
306 public static function base_login_return()
307 {
308
309 $consumer = self::getConsumer();
310
311 $response = $consumer->complete();
312
313 if ($response->status == Auth_OpenID_CANCEL) {
314 return 'Verification cancelled.';
315 } else if ($response->status == Auth_OpenID_FAILURE) {
316 return $response->message;
317 } else if ($response->status == Auth_OpenID_SUCCESS) {
318 return $response;
319 }
320 }
321}