forked from arusso/CASAuth
-
Notifications
You must be signed in to change notification settings - Fork 5
/
CASAuth.php
310 lines (254 loc) · 11.1 KB
/
CASAuth.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
<?php
/*
* CASification script for MediaWiki 1.27 with phpCAS 1.3.3
*
* Requires phpCAS: https://wiki.jasig.org/display/CASC/phpCAS
* Install by adding this line to LocalSetting.php:
* require_once("$IP/extensions/CASAuth/CASAuth.php");
*
* *** Please keep all configuration in the CASAuthSettings.php file ***
*
* Revision History
* Original Revision: Ioannis Yessios
* ioannis [dot] yessios [at] yale [dot] edu
* Single Sign-Out code and more: Hauke Pribnow
* hauke [dot] pribnow [at] gmx [dot] de
* Worked with the code: Christophe Naslain
* chris [dot] n [at] free [dot] fr
* Which was based on the original script using CAS Utils by Victor Chen
* Yvchen [at] sfu [dot] ca
* Cleaned up and bugfixed: Stefan Sundin
* recover89 [at] gmail [dot] com
* User filtering code, seperation of config and code cleanup: Aaron Russo
* arusso [at] berkeley [dot] edu
* Email lookup hook added: Amir Tahvildaran
* amirdt22 [at] gmail [dot] com
* MW 1.27 compatibility: Jeffrey Gill
* jeffrey [dot] p [dot] gill [at] gmail [dot] com
* Security patch (user name trimming): Andrew Engelbrecht (contribution under GPLv2-or-later)
* andrew [at] engelbrecht [dot] io
*/
$wgExtensionCredits["other"][] = array(
"name" => "CASAuth",
"version" => "2.0.4",
"author" => "Ioannis Yessios, Hauke Pribnow, Aaron Russo, Jeffrey Gill",
"url" => "https://github.com/CWRUChielLab/CASAuth",
"description" => "Overrides MediaWiki's Authentication and implements Central Authentication Service (CAS) Authentication. Original url: http://www.mediawiki.org/wiki/Extension:CASAuthentication"
);
//--------------------------------------------------------------------------
// Configuration Variable Defaults - See CASAuth.conf
//--------------------------------------------------------------------------
$CASAuth = array(
"phpCAS" => "$IP/extensions/CASAuth/CAS",
"Server" => "auth.example.com",
"LogoutServers" => false,
"Port" => 443,
"Url" => "/cas/",
"Version" => "2.0",
"CreateAccounts" => false,
"PwdSecret" => "Secret",
"EmailDomain" => "example.com",
"RememberMe" => true,
"AllowedUsers" => false,
"RestrictUsers" => false,
);
# load our custom configuration
require_once(__DIR__ . "/CASAuthSettings.php");
//--------------------------------------------------------------------------
// CASAuth
//--------------------------------------------------------------------------
// Setup hooks
global $wgHooks;
$wgHooks["UserLoadAfterLoadFromSession"][] = "casLogin";
$wgHooks["UserLogoutComplete"][] = "casLogout";
$wgHooks["GetPreferences"][] = "casPrefs";
global $wgExtensionFunctions;
$wgExtensionFunctions[] = 'casLogoutCheck';
global $casIsSetUp;
$casIsSetUp = false;
// Check if there was a valid single sign-out message that terminated this session
function casLogoutCheck() {
global $CASAuth;
if(isset($_SESSION['wsCASLoggedOut']) && $_SESSION['wsCASLoggedOut']) {
global $wgUser;
$wgUser->logout();
unset($_SESSION['wsCASLoggedOut']);
unset($_SESSION['phpCAS']);
}
}
// Login
function casLogin($user) {
global $CASAuth;
global $casIsSetUp;
global $wgRequest, $wgOut;
if (isset($_REQUEST["title"])) {
if ($_REQUEST["title"] == SpecialPage::getTitleFor("Userlogin")->getPrefixedDBkey()) {
// Load phpCAS
if(!$casIsSetUp)
casSetup();
//Will redirect to CAS server if not logged in
phpCAS::forceAuthentication();
// Get username
$username = casNameLookup(phpCAS::getUser());
// casNameLookup() says name is invalid
if (is_null($username)) {
// redirect user to the RestrictRedirect page
$wgOut->redirect($CASAuth["RestrictRedirect"]);
return true;
}
// If we are restricting users AND the user is not in
// the allowed users list, lets block the login
if($CASAuth["RestrictUsers"]==true
&& !in_array($username,$CASAuth["AllowedUsers"]))
{
// redirect user to the RestrictRedirect page
$wgOut->redirect($CASAuth["RestrictRedirect"]);
return true;
}
// Get MediaWiki user
$u = User::newFromName($username);
// MediaWiki says name is invalid
if ($u === false) {
// redirect user to the RestrictRedirect page
$wgOut->redirect($CASAuth["RestrictRedirect"]);
return true;
}
// Create a new account if the user does not exists
if ($u->getID() == 0 && $CASAuth["CreateAccounts"]) {
//Get email and realname
$realname = casRealNameLookup(phpCAS::getUser());
$email = casEmailLookup(phpCAS::getUser());
// Create the user
$u->addToDatabase();
$u->setRealName($realname);
$u->setEmail($email);
// PwdSecret is used to salt the username, which is
// then used to create an md5 hash which becomes the
// password
$u->setPassword(
md5($username.$CASAuth["PwdSecret"])
);
$u->setToken();
$u->saveSettings();
// Update user count
$ssUpdate = new SiteStatsUpdate(0,0,0,0,1);
$ssUpdate->doUpdate();
}
// Login successful
if ($CASAuth["RememberMe"]) {
$u->setOption("rememberpassword", 1);
}
$u->setCookies(null, null, $CASAuth["RememberMe"]);
$user = $u;
// Redirect if a returnto parameter exists
$returnto = $wgRequest->getVal("returnto");
if ($returnto) {
$target = Title::newFromText($returnto);
if ($target) {
//action=purge is used to purge the cache
$wgOut->redirect($target->getFullUrl('action=purge'));
}
}
}
}
// Back to MediaWiki home after login
return true;
}
// Logout
function casLogout() {
global $CASAuth;
global $casIsSetUp;
global $wgRequest;
// Get returnto value
$returnto = $wgRequest->getVal("returnto");
if ($returnto) {
$target = Title::newFromText($returnto);
if ($target && $target->getPrefixedDBkey() != SpecialPage::getTitleFor("Userlogout")->getPrefixedDBkey()) {
$redirecturl = $target->getFullUrl();
}
}
if(!$casIsSetUp)
casSetup();
// Logout from CAS (will redirect user to CAS server)
if (isset($redirecturl)) {
phpCAS::logoutWithRedirectService($redirecturl);
}
else {
phpCAS::logout();
}
return true; // We won't get here
}
// Remove reset password link and remember password checkbox from preferences page
function casPrefs($user, &$preferences) {
unset($preferences["password"]);
unset($preferences["rememberpassword"]);
return true;
}
// Store the session name and id in a new logout ticket session to be able
// to find it again when single signing-out
function casPostAuth($ticket2logout) {
// remember the current session name and id
$old_session_name=session_name();
$old_session_id=session_id();
// close the current session for now
session_write_close();
session_unset();
session_destroy();
// create a new session where we'll store the old session data
session_name("casauthssoutticket");
session_id(preg_replace('/[^a-zA-Z0-9\-]/','',$ticket2logout));
session_start();
$_SESSION["old_session_name"] = $old_session_name;
$_SESSION["old_session_id"] = $old_session_id;
// close the ssout session again
session_write_close();
session_unset();
session_destroy();
// and open the old session again
session_name($old_session_name);
session_id($old_session_id);
session_start();
}
// The CAS server sent a single sign-out command... let's process it
function casSingleSignOut($ticket2logout) {
global $CASAuth;
$session_id = preg_replace('/[^a-zA-Z0-9\-]/','',$ticket2logout);
// destroy a possible application session created before phpcas
if(session_id() !== ""){
session_unset();
session_destroy();
}
// load the ssout session
session_name("casauthssoutticket");
session_id($session_id);
session_start();
// extract the user session data
$old_session_name = $_SESSION["old_session_name"];
$old_session_id = $_SESSION["old_session_id"];
// close the ssout session again
session_unset();
session_destroy();
// load the user session
session_name($old_session_name);
session_id($old_session_id);
session_start();
// set the flag that the user session is to be closed
$_SESSION['wsCASLoggedOut'] = true;
// close the user session again
session_write_close();
session_unset();
session_destroy();
}
function casSetup() {
global $CASAuth;
global $casIsSetUp;
// Make the session persistent so that phpCAS doesn't change the session id
wfSetupSession();
require_once($CASAuth["phpCAS"]."/CAS.php");
phpCAS::client($CASAuth["Version"], $CASAuth["Server"], $CASAuth["Port"], $CASAuth["Url"], false);
phpCAS::setSingleSignoutCallback('casSingleSignOut');
phpCAS::setPostAuthenticateCallback('casPostAuth');
phpCAS::handleLogoutRequests(true,isset($CASAuth["LogoutServers"])?$CASAuth["LogoutServers"]:false);
phpCAS::setNoCasServerValidation();
$casIsSetUp = true;
}