I'm fairly to MediaWiki and needed a way to automatically log users in after they authenticated to a central server (which creates a session and cookie for applications to use).
I wrote a custom authentication extension based off of the LDAP Authentication extension and a few others. The extension simply needs to read some session data to create or update a user and then log them in automatically. All the authentication is handled externally. A user would not be able to even access the wiki website without logging in externally.
This extension was placed into production which replaced the old standard MediaWiki authentication system. I also merged user accounts to prepare for the change. By default, a user must be logged in to view, edit, or otherwise do anything in the wiki.
My problem is that I found if a user had previously used the built-in MediaWiki authentication system and returned to the wiki, my extension would attempt to auto-login the user, however, they would see a "Login Required" page instead of the page they requested like they were an anonymous user. If the user then refreshed the page, they would be able to navigate, edit, etc.
From what I can tell, this issue resolves itself after the UserID cookie is reset or created fresh (but has been known to strangely come up sometimes). To replicate, if there is an older User ID in the "USERID" cookie, the user is shown the "Login Required" page which is a poor user experience. Another way of showing this page is by removing the user account from the database and refreshing the wiki page. As a result, the user will again see the "Login Required" page.
Does anyone know how I can use debugging to find out why MediaWiki thinks the user is not signed in when the cookies are set properly and all it takes is a page refresh?
Here is my extension (simplified a little for this post):
<?php
$wgExtensionCredits['parserhook'][] = array (
'name' => 'MyExtension',
'author' => '',
);
if (!class_exists('AuthPlugin')) {
require_once ( 'AuthPlugin.php' );
}
class MyExtensionPlugin extends AuthPlugin {
function userExists($username) {
return true;
}
function authenticate($username, $password) {
$id = $_SESSION['id'];
if($username = $id) {
return true;
} else {
return false;
}
}
function updateUser(& $user) {
$name = $user->getName();
$user->load();
$user->mPassword = '';
$user->mNewpassword = '';
$user->mNewpassTime = null;
$user->setRealName($_SESSION['name']);
$user->setEmail($_SESSION['email']);
$user->mEmailAuthenticated = wfTimestampNow();
$user->saveSettings();
return true;
}
function modifyUITemplate(& $template) {
$template->set('useemail', false);
$template->set('remember', false);
$template->set('create', false);
$template->set('domain', false);
$template->set('usedomain', false);
}
function autoCreate() {
return true;
}
function disallowPrefsEditByUser() {
return array (
'wpRealName' => true,
'wpUserEmail' => true,
'wpNick' => true
);
}
function allowPasswordChange() {
return false;
}
function setPassword( $user, $password ) {
return false;
}
function strict() {
return true;
}
function initUser( & $user ) {
}
function updateExternalDB( $user ) {
return false;
}
function canCreateAccounts() {
return false;
}
function addUser( $user, $password ) {
return false;
}
function getCanonicalName( $username ) {
return $username;
}
}
function SetupAuthMyExtension() {
global $wgHooks;
global $wgAuth;
$wgHooks['UserLoadFromSession'][] = 'Auth_MyExtension_autologin_hook';
$wgHooks['UserLogoutComplete'][] = 'Auth_MyExtension_UserLogoutComplete';
$wgHooks['PersonalUrls'][] = 'Auth_MyExtension_personalURL_hook';
$wgAuth = new MyExtensionPlugin();
}
function Auth_MyExtension_autologin_hook($user, &$return_user ) {
global $wgUser;
global $wgAuth;
global $wgContLang;
wfSetupSession();
// Give us a user, see if we're around
$tmpuser = new User() ;
$rc = $tmpuser->newFromSession();
$rc = $tmpuser->load();
if( $rc && $rc->isLoggedIn() ) {
if ( $rc->authenticate($rc->getName(), '') ) {
return true;
} else {
$rc->logout();
}
}
$id = trim($_SESSION['id']);
$name = ucfirst(trim($_SESSION['name']));
if (empty($dsid)) {
$result = false; // Deny access
return true;
}
$user = User::newFromName($dsid);
if (0 == $user->getID() ) {
// we have a new user to add...
$user->setName( $id);
$user->addToDatabase();
$user->setToken();
$user->saveSettings();
$ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
$ssUpdate->doUpdate();
} else {
$user->saveToCache();
}
// update email, real name, etc.
$wgAuth->updateUser( $user );
$result = true;
// Go ahead and log 'em in
$user->setToken();
$user->saveSettings();
$user->setupSession();
$user->setCookies();
return true;
}
function Auth_MyExtension_personalURL_hook(& $personal_urls, & $title) {
global $wgUser;
unset( $personal_urls['mytalk'] );
unset($personal_urls['Userlogin']);
$personal_urls['userpage']['text'] = $wgUser->getRealName();
foreach (array('login', 'anonlogin') as $k) {
if (array_key_exists($k, $personal_urls)) {
unset($personal_urls[$k]);
}
}
return true;
}
function Auth_MyExtension_UserLogoutComplete(&$user, &$inject_html, $old_name) {
setcookie( $GLOBALS['wgCookiePrefix'] . '_session', '', time() - 3600, $GLOBALS['wgCookiePath']);
setcookie( $GLOBALS['wgCookiePrefix'] . 'UserName', '', time() - 3600, $GLOBALS['wgCookiePath']);
setcookie( $GLOBALS['wgCookiePrefix'] . 'UserID', '', time() - 3600, $GLOBALS['wgCookiePath']);
setcookie( $GLOBALS['wgCookiePrefix'] . 'Token', '', time() - 3600, $GLOBALS['wgCookiePath']);
return true;
}
?>
Here is part of my LocalSettings.php file:
#############################
# Disallow Anonymous Access
#############################
$wgGroupPermissions['*']['read'] = false;
$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['*']['createpage'] = false;
$wgGroupPermissions['*']['createtalk'] = false;
$wgGroupPermissions['*']['createaccount'] = false;
$wgShowIPinHeader = false; # For non-logged in users
#############################
# Extension: MyExtension
#############################
require_once("$IP/extensions/MyExtension.php");
$wgAutoLogin = true;
SetupAuthMyExtension();
$wgDisableCookieCheck = true;