MediaWiki remote user authentication

A Mediawiki has it’s own authentication, the users and all user information is stored in the database. Our current infrastructure has our users stored in a central ldap database and the authentication happens by apache’s Basic Auth.

This means that when a user tries to access the wiki for the first time he has to authenticate to the apache, then he needs to create an account on the mediawiki and he has to login on the mediawiki. The other times he still has to login 2 times.

These 2 things (mediawiki registration and authentication) can go automatically, you only need to edit 1 file and add 1 file.

I found the necessary info on following page: http://meta.wikimedia.org/wiki/User:Otheus/Auto_Login_via_REMOTE_USER but it didn’t work out of the box. I started to try it step-by-step, some parts aren’t necessary to make it work.

MediaWiki has a class that can be overwritten whenever you want to register remote users. It is located in includes/AuthPlugin.php and has a lot of comments which explains what the functions do. The easiest way to do is to copy the file to a new file (includes/Auth_remoteuser.php in my example) and start editing the new file.
You have to include the original file and edit the class definition rule.

require_once('AuthPlugin.php');

#class AuthPlugin {
class Auth_remoteuser extends AuthPlugin {

If you have edited all necessary functions of that class (the functions you didn’t edit can be deleted). You also have to add a constructor class which will add an extensionFunction. The function that will be added as extensionFunction is defined in the next step.

function Auth_remoteuser() {
    if ( strlen($_SERVER['PHP_AUTH_USER']) ) {
        global $wgExtensionFunctions;
        if (!isset($wgExtensionFunctions)) {
            $wgExtensionFunctions = array();
        } else if (!is_array($wgExtensionFunctions)) {
            $wgExtensionFunctions = array( $wgExtensionFunctions );
        }
        array_push($wgExtensionFunctions, 'Auth_remote_user_hook');
    }
    return;
}

The function can be added in the same file, above or below the class.

function Auth_remote_user_hook() {
    global $wgUser;
    global $wgRequest;
    global $_REQUEST;

    // For a few special pages, don't do anything.
    $title = $wgRequest->getVal('title') ;
    if ($title == 'Special:Userlogout' || $title == 'Special:Userlogin') {
         return;
    }

    // Do nothing if session is valid
    $wgUser = User::loadFromSession();
    if ($wgUser->isLoggedIn()) {
        return;
    }

    $username = $_SERVER['PHP_AUTH_USER' ];
    $u = User::newFromName( $username );
    if (is_null($u)) {
        # Invalid username or some other error -- force login, just return
        return;
    }

    $wgUser = $u;
    if ($u->getId() != 0) {
        $_REQUEST['wpName'] = $username;
        # also return, but user is know. set Cookies, et al
        $wgUser->setCookies();
        $wgUser->saveSettings();
        return;
    }

    // Ok, now we need to create a user.
    include 'includes/SpecialUserlogin.php';
    $form = new LoginForm( $wgRequest );
    $form->initUser( $wgUser );
    $wgUser->saveSettings();
}

The final thing you have to do is edit the LocalSettings.php file and add folowing 2 lines. Once this is done the code is activated.

require_once('includes/Auth_remoteuser.php');
$wgAuth = new Auth_remoteuser();

All necessary code is changed and whenever you now login to the Basic Auth of apache and you access MediaWiki you account will be created and you will get automatically logged in.

The full includes/Auth_remoteuser.php I use can be downloaded here.

This is how it works:
Every page you access will call the LocalSettings.php file. In that file the Auth_remoteuser class will be called. The constructor of that class will be called and the Auth_remote_user_hook function will be added to the ExternalFunctions array and executed.
This function will first test if you are on the login or logout page, if so it won’t do anything.
If you are already logged in it also won’t do anything.
If you aren’t logged in and you are already registerd it will log in.
If you don’t have an account, an account will be created and you will get logged in.

26 Comments

  1. Robb said:

    Thank you for publishing your findings, Raskas!
    Have you tried your code with MediaWiki 1.9? I am trying to get this to work, but am getting:

    Fatal error: Using $this when not in object context in https://host.example.com/mediawiki-1.9.0/includes/User.php on line 642.

    I am not very familiar with PHP, so I am doing my best to track down the cause. However, any insights you might have would be great.

  2. Wouter de Bie said:

    For 1.9, modify replace the small block of code on line 259 to:

    // Do nothing if session is valid
    $wgUser = new User();
    $wgUser->loadFromSession();
    if ($wgUser->isLoggedIn()) {
    return;
    }

    The problem is that loadFromSession() uses $this, but in the Auth_remoteuser, the user is loaded not by instantiating a user object, but just calling loadFromSession() as a static method. The code above worked for me..

  3. Lewis Jones said:

    Thanks, Raskas.

    This seems to be exactly what I’ve been looking for. I’m not a server expert or brilliant with PHP, but it seems to me this scheme works if the common login is at the server level.

    I am using Typo3 cms to manage my site, but I want to integrate MediaWiki and other applications as well. The cms handles logins to the site and, other than occurring on the server, as it were, my users are not logging into the server. The cms maintains its own user table, while logging into the server is something different again.

    Anyway, I realise you understand all this much better than I do. I would like to use your method to create a single transparent login and user creation for the site through the Typo3 cms login and user registration.

    It seems to me, there wouldn’t be too much to modfiy in what you’ve done, to make that happen. Is it possible to point me in the right direction as to what modifications would be required?

    Thanks again. What you’ve done here is the most helpful thing I’ve seen on the subject.

  4. Johan Huysmans said:

    The first step is finding your username (and password). If you were using HTTP authentication it was easy:
    $username = $_SERVER['PHP_AUTH_USER' ];
    $password = $_SERVER['PHP_AUTH_PW' ];

    But this isn’t the case. So you have to find out where typo3 saves its userinfo. This can be in cookies or more likely in your session data.

    Once you have that data you have to edit the code of your other projects and have to find out how you can automatically login.

    Good luck!

  5. Martin said:

    Hello,

    i used your howto as a reference for our sso media wiki extension, btw. I installed a recent version of MediaWiki. Your fix doesn’t work:

    // Do nothing if session is valid
    $wgUser = new User();
    $wgUser->loadFromSession();
    if ($wgUser->isLoggedIn()) {
    return;
    }

    I changed it to:
    // Do nothing if session is valid
    $wgUser = User::newFromSession();
    if ($wgUser->isLoggedIn()) {
    return;
    }

    and it works just fine for me.

    Thanks for your howto.

    Greetings,
    Martin

  6. Kanwar said:

    I have one problem with this working, if i try to logout and browse other link while i am logged out, it logs me back in with the previous username,
    what can we do about it, please help

  7. Ryan said:

    Hey, thanks a lot for this information. I seem to have reached an endpoint and I am not sure where to go from here so I thought I’d ask for some advice. We have an internal authentication system in our office that authorizes a user at a central location, then, I grab the user information from the headers. I do not have the password as it is stored with the central server, but the connection has been established and the user is substantially authenticated that I do not need to perform checks on my side. I only need to create the account and authenticate the user with mediawiki based on the username appearing in the header.

    I am receiving the following error when I enabled $wgShowExceptionDetails = true; in LocalSettings.php.

    setPassword(”)
    #1 /var/www/wiki/includes/AuthPluginAddOn.php(304): LoginForm->initUser(Object(User))
    #2 [internal function]: Auth_remote_user_hook()
    #3 /var/www/wiki/includes/Setup.php(219): call_user_func(’Auth_remote_use…’)
    #4 /var/www/wiki/includes/WebStart.php(90): require_once(’/var/www/wiki/i…’)
    #5 /var/www/wiki/index.php(4): require_once(’/var/www/wiki/i…’)
    #6 {main}
    >>

    It appears that Media wiki does not like the blank password? Is this the case? Is there a way around this?

    Thank you for the help and advice!

  8. Ryan said:

    My cut and paste missed the top part of the error:

    Internal error

    <password-change-forbidden>

    Backtrace:

    #0 /var/www/wiki/includes/SpecialUserlogin.php(311): User->setPassword(”)
    #1 /var/www/wiki/includes/AuthPluginSns.php(304): LoginForm->initUser(Object(User))
    #2 [internal function]: Auth_remote_user_hook()
    #3 /var/www/wiki/includes/Setup.php(219): call_user_func(’Auth_remote_use…’)
    #4 /var/www/wiki/includes/WebStart.php(90): require_once(’/var/www/wiki/i…’)
    #5 /var/www/wiki/index.php(4): require_once(’/var/www/wiki/i…’)
    #6 {main}

  9. Ryan said:

    Nevermind, I commented out password authentication and it worked!

  10. Jeff said:

    I just wanted to say for reference, for those google searchers, that with MediaWiki 1.10.1, here is what worked for me:

    The file Auth_remoteusers.php referenced above (I just downloaded http://www.raskas.be/blog_links/Auth_remoteuser.phps), coupled with the change Martin (May 4th, 2007 at 12:15) proposed. Once I enabled it in the LocateSettings.php, it worked right away with that combination.

  11. nmonkee said:

    Error: Sorry! We could not process your edit due to a loss of session data. Please try again. If it still doesn’t work, try logging out and logging back in.

    Version: MediaWiki 1.9.3

    Problem: Since applying the hack, wich works pretty well, I recieve the error above when making edits.

  12. Keith said:

    As a follow-on to Jeff’s comment, I can confirm that the same configuration that he reports will work for 1.10.1 will also work for 1.11.0 (original file + Martin’s mod + LocalSettings.php call).

  13. David said:

    I got this to work and i love it. Is there a way to based on the external auth db which determines if a user is an admin to set the current user’s session to a ’sysop’ role when authenticated?

    1) either in the InitForm to add the user to the user_groups as a sysop

    or

    2.) Just load the session with the sysop like user->mGroups[] = ’sysop’

    Thanks …

  14. Ravi Gurbaxani said:

    I am a complete newbie and have been given a task of installing mediawiki 1.10 and integrate it with the existing application. I would try to be specific in terms of what I know and what I need

    My Goal
    I have a WAMP server installation on my local machine. I am hosting an application for Knomledge Management and there needs to be a link on the homepage which will take the user to the wiki. The user need not login again.

    My Doubts
    1) PHP_AUTH_USER: Does it gets created once I login in an application with username and password that validates it from database or it gets created when I enter the credentials in a IE windows pop up form. I have spend 2 days trying to echo PHP_AUTH_USER but it gets created only when I use “header(’WWW-Authenticate: Basic realm=”My Realm”‘)”

    2) Why is this kind of authentication required.

    3) From my homepge when I create a link to the wiki. What should be the link that will be given in ahref is it http://localhost/mediawiki or there will be some more parameters that will be passed

    4) In this post, the first line says ldap database is ready, so is ldap the only way.

    Please suggest me what accoring to you will be the best way to go forward.
    Thanks in advance

  15. Ravi Gurbaxani said:

    My previous comment was a bit rude. Sorry for that

  16. Dee said:

    It works for me with one exclusion: I have to get commented following part:
    // Do nothing if session is valid
    // $wgUser = User::loadFromSession();
    // if ($wgUser->isLoggedIn()) {
    // return;
    // }
    there was an error displayed on my system. Using https, Apache/2.2.4 (Win32), OpenSSL/0.9.8e, PHP/5.2.3

  17. Etenil said:

    Hi there, I had to hack it a little too for it to work with Mediawiki 1.11

    here is the first hack:

    $wgUser = User::loadFromSession();
    if ($wgUser->isLoggedIn()) {
    return;
    }

    becomes:

    $wgUser = new User();
    $wgUser->load();
    if ($wgUser->isLoggedIn()) {
    return;
    }

    then I did this:
    $_SERVER['PHP_AUTH_USER']
    becomes
    $_SERVER['REMOTE_USER' ]

    and things work perfectly.

    Thank you for the hack btw.

  18. timhessel said:

    I’m currently trying to install this plugin, but I encounter some errors (in MW 1.12.0)

    I have already replaced $_SERVER[’PHP_AUTH_USER’] with $_SERVER[’REMOTE_USER’ ], but still I keep getting the following error:

    “Notice: Undefined index: REMOTE_USER in /var/www/”

    Apparently $_SERVER['REMOTE_USER'] isn’t set anymore in MW 1.12.0 if not logged in. I fixed this by replacing
    strlen($_SERVER['REMOTE_USER'] with isset($_SERVER['REMOTE_USER']

    Hope this helps anyone trying to use it with MW 1.12.0

  19. timhessel said:

    Disregard that last comment, it’s nonsense. I need to look at my code a little better though :P

  20. Rich said:

    Im a relative newbie with mediawiki and have been given the task of implementing mediawiki, on a Windows 2003 server running IIS, using php and a mysql DB. One of the requirements is that users are logged in automatically to mediawiki via their domain credentials. To be honest im really unsure how to go about this as REMOTE_USER etc that i have seen i believe are not relevant for my specifications. Any help would be a God send!!

    Rich

  21. Will Neelen said:

    FOR RICH

    I got this to work on Windows 2003 server running IIS.
    It even works if you have multiple domains in a forrest.
    Below the configuration for a single domain.

    You need to 3 things
    1. Set IIS configuration
    2. Download Auth_remoteuser_iis.php
    3. Add settings to LocalSettings.php

    1. In IIS,
    under the website configuration,
    tab Directory Security /
    Authentication and acces control /
    username: your_domain\your_remote_user
    password: your_remote_users_password
    UNMARK anonymous access
    Apply these settings for underlying virtual directories.

    2. Download Auth_remoteuser_iis.php
    And put it in the extensions folder

    3. Add the settings below to LocalSettings.php
    Change the variables to:
    -your domain
    -your DC
    -your DNS server
    - the remote user account in your domain

    # SECURITY section added for SSO
    $wgGroupPermissions['*']['createaccount'] = false;
    $wgGroupPermissions['*']['read'] = false;
    $wgGroupPermissions['*']['edit'] = false;
    # Pages anonymous (not-logged-in) users may see
    $wgWhitelistRead = array( “Main Page”, “Special:Userlogin”, “-”, “MediaWiki:Monobook.css” );
    # Remote_User Auth with MS AD LDAP enhancements
    require_once(’extensions/Auth_remoteuser_iis.php’);
    $wgAuth = new Auth_remoteuser();
    $wgLDAPServerNames = array( “YOUR_DOMAIN”=>”first_domaincontroller.yourdomain.com”, second_domaincontroller.yourdomain.com”);
    $wgLDAPSearchStrings = array( “YOUR_DOMAIN”=>”USER-NAME” );
    $wgLDAPBindUsers = array( “your_remote_user_account your_remote_users_password” );
    $wgLDAPBaseDNs = array( “YOUR_DOMAIN”=>”DC=YOUR_DOMAINS_DNS_SERVER.YOUR_DOMAIN.com, DC=YOUR_DOMAIN.com” );
    $wgLDAPDebug = 0;

  22. Michael Raugh said:

    Just a report for the good of the lodge, as it were.

    I just installed this mod on MediaWiki 1.13.3 using the code from here, which Raskas referenced at the top of the blog entry.

    I used Etenil’s tweak to the Auth_remoteuser.php (though there is no usage of ‘PHP_AUTH_USER’ in the version I started with) and I also had to change the ownership of /var/lib/php/session (chown -R apache:web /var/lib/php/session) to get around an “Error saving session data” problem when trying to edit a page.

    Side note: once a user has accessed the wiki (and therefore had an account auto-created) you can assign them any group memberships you like using the normal means. For me that’s editing the user_groups table in mySQL directly, but your methods may vary.

  23. Michael Raugh said:

    Oops — I should cite the whole platform, I suppose.

    Apache 2.2.3
    CentOS 5 (RHEL 5 clone)
    MediaWiki 1.13.3

    My external authentication source is LDAP over SSL, configured via the standard Apache mod_authz_ldap module. Shouldn’t matter though, as it’s transparent to MediaWiki.

  24. Robert Kuszinger said:

    Hello!

    I’m trying to set up alternative authentication to a WIKI. I’d like to ask if your solution could work with mediawiki 1.14.
    I’ve set up the pwauth recipe, login is successful, however, user won’t be in a logged in state…

    If your recipe above works with 1.14 as far as you know, I’d modify it to use pwauth (or whatever) for authentication…

    thanks for any help.
    Robert Kuszinger

  25. Daniel said:

    I have MediWiki 1.13.3 running. Authentication via remote user only works partially: On the first time I call a wiki-page, I am shown the login page. If I go to another page or simply hit refresh, I am logged in and everything is fine.
    Does anybody have a clue how to solve this problem? Thanks a lot in advance.

    Regards, Daniel

  26. Jaya said:

    Just to update. I tried this method with the modifications suggested by Etenil for Mediawiki 1.15.1 and it works fine for me. Thanks Raskas!

Leave a Reply