MediaWiki - simple setup for external http authentication (Raven)
mediawiki 1.9.4
These hacks all assume that the Mediawiki application is first protected by something that sets the REMOTE_USER apache server variable, such as the [http://raven.cam.ac.uk/project/apache/ Raven Apache authentication module].
The hacks for 1.5.2 have been really useful, but I've had a couple of problems (maybe my fault as I notice this wiki is fine with both of these things):
- upload of files requires creation of a "real" wiki account, which Raven users can do, but is a slight faff
- changes are logged against IP rather than Raven ID
This
media-wiki extension (Extension:AutomaticREMOTE USER) solves both of these problems, for me, and is easy to implement.
Documentation in case the above disappears
After installing mediawiki put the text below into extensions/Auth_remoteuser.php
and add these two lines to the bottom of your LocalSettings.php:
require_once('extensions/Auth_remoteuser.php');
$wgAuth = new Auth_remoteuser();
extensions/Auth_remoteuser.php contains:
getVal('title');
if (($title == Title::makeName(NS_SPECIAL, 'Userlogout')) ||
($title == Title::makeName(NS_SPECIAL, 'Userlogin'))) {
return;
}
// Do nothing if session is valid
$user = User::newFromSession();
if (!$user->isAnon()) {
return; // User is already logged in and not anonymous.
}
// Copied from includes/SpecialUserlogin.php
if(!isset($wgCommandLineMode) && !isset($_COOKIE[session_name()])) {
wfSetupSession();
}
// Submit a fake login form to authenticate the user.
$username = $_SERVER['REMOTE_USER' ];
$params = new FauxRequest(array(
'wpName' => $username,
'wpPassword' => '',
'wpDomain' => '',
'wpRemember' => ''
));
// Authenticate user data will automatically create new users.
$loginForm = new LoginForm($params);
$result = $loginForm->authenticateUserData();
if ($result != LoginForm::SUCCESS) {
error_log('Unexpected REMOTE_USER authentication failure.');
return;
}
$wgUser->setCookies();
return; // User has been logged in.
}
class Auth_remoteuser extends AuthPlugin {
function Auth_remoteuser() {
// Register our hook function. This hook will be executed on every page
// load. Its purpose is to automatically log the user in, if necessary.
if ( strlen($_SERVER['REMOTE_USER']) ) {
global $wgExtensionFunctions;
if (!isset($wgExtensionFunctions)) {
$wgExtensionFunctions = array();
}
else if (!is_array($wgExtensionFunctions)) {
$wgExtensionFunctions = array( $wgExtensionFunctions );
}
array_push($wgExtensionFunctions, 'Auth_remote_user_hook');
}
return;
}
/**
* Disallow password change.
*
* @return bool
*/
# mr349, 25/09/2007
function allowPasswordChange() {
return true;
}
/**
* This should not be called because we do not allow password change. Always
* fail by returning false.
*
* @param $user User object.
* @param $password String: password.
* @return bool
* @public
*/
# mr349, 25/09/2007
function setPassword($user, $password) {
return true;
}
/**
* We don't support this but we have to return true for preferences to save.
*
* @param $user User object.
* @return bool
* @public
*/
function updateExternalDB($user) {
return true;
}
/**
* We can't create external accounts so return false.
*
* @return bool
* @public
*/
function canCreateAccounts() {
return false;
}
/**
* We don't support adding users to whatever service provides REMOTE_USER, so
* fail by always returning false.
*
* @param User $user
* @param string $password
* @return bool
* @public
*/
function addUser($user, $password) {
return false;
}
/**
* Pretend all users exist. This is checked by authenticateUserData to
* determine if a user exists in our 'db'. By returning true we tell it that
* it can create a local wiki user automatically.
*
* @param $username String: username.
* @return bool
* @public
*/
function userExists($username) {
return true;
}
/**
* Check whether the given name matches REMOTE_USER.
* The name will be normalized to MediaWiki's requirements, so
* lower it and the REMOTE_USER before checking.
*
* @param $username String: username.
* @param $password String: user password.
* @return bool
* @public
*/
function authenticate($username, $password) {
global $_SERVER;
return isset($_SERVER['REMOTE_USER']) &&
(strtolower($username) == strtolower($_SERVER['REMOTE_USER']));
}
/**
* Check to see if the specific domain is a valid domain.
*
* @param $domain String: authentication domain.
* @return bool
* @public
*/
function validDomain($domain) {
return true;
}
/**
* When a user logs in, optionally fill in preferences and such.
* For instance, you might pull the email address or real name from the
* external user database.
*
* The User object is passed by reference so it can be modified; don't
* forget the & on your function declaration.
*
* @param User $user
* @public
*/
function updateUser(&$user) {
// We only set this stuff when accounts are created.
return true;
}
/**
* Return true because the wiki should create a new local account
* automatically when asked to login a user who doesn't exist locally but
* does in the external auth database.
*
* @return bool
* @public
*/
function autoCreate() {
return true;
}
/**
* Return true to prevent logins that don't authenticate here from being
* checked against the local database's password fields.
*
* @return bool
* @public
*/
function strict() {
return true;
}
/**
* When creating a user account, optionally fill in preferences and such.
* For instance, you might pull the email address or real name from the
* external user database.
*
* @param $user User object.
* @public
*/
function initUser(&$user) {
global $_SERVER;
$username = $_SERVER['REMOTE_USER'];
// Using your own methods put the users real name here.
$user->setRealName('');
// Using your own methods put the users email here.
$user->setEmail($username . '@example.com');
$user->mEmailAuthenticated = wfTimestampNow();
$user->setToken();
//turn on e-mail notifications by default
$user->setOption('enotifwatchlistpages', 1);
$user->setOption('enotifusertalkpages', 1);
$user->setOption('enotifminoredits', 1);
$user->setOption('enotifrevealaddr', 1);
$user->saveSettings();
}
/**
* Modify options in the login template. This shouldn't be very important
* because no one should really be bothering with the login page.
*
* @param $template UserLoginTemplate object.
* @public
*/
function modifyUITemplate(&$template) {
//disable the mail new password box
$template->set('useemail', false);
//disable 'remember me' box
$template->set('remember', false);
$template->set('create', false);
$template->set('domain', false);
$template->set('usedomain', false);
}
/**
* Normalize user names to the mediawiki standard to prevent duplicate
* accounts.
*
* @param $username String: username.
* @return string
* @public
*/
function getCanonicalName($username) {
// lowercase the username
$username = strtolower($username);
// uppercase first letter to make mediawiki happy
$username[0] = strtoupper($username[0]);
return $username;
}
}
?>
Yes, I have commented my code changes with my CRSID, feel free to replace the comments.
The code changes:
Line 111 of ./extensions/Auth_remoteuser.php change the false from:
function allowPasswordChange() {
return false;
}
to:
function allowPasswordChange() {
return true;
}
Same for line 124:
function setPassword($user, $password) {
return false;
}
to:
function setPassword($user, $password) {
return true;
}
|