Extension talk:Siteminder Authentication

From mediawiki.org
Latest comment: 9 years ago by Coordinatesystem in topic Merged in changes, tested 1.23

Login Not Required for View Only[edit]

I have this plugin working and it works great. It is designed to require a login even for viewing. Has anyone been able to set this up so that you don't have to Authenticate for view only?

While I am only a Siteminder user (others in my organization are responsible for Siteminder administration), I believe you are asking a question that is better directed to your Siteminder administrators. That product can restrict to the specific URL, so you could restrict access to the login page which would trigger Siteminder only when attempting to login. That said, I suggest you visit the Extension:Shibboleth Authentication article and review the configuration there. It is designed to have a separate link that allows login via Shibboleth in addition to the regular login link. That is a collaborative effort between the extension and the Shibboleth configuration. A similar collaboration would be needed between the Siteminder product and this extension.--Vjg 11:40, 2 April 2008 (UTC)Reply

Extension Configured with WikiMedia Version 1.13.0 final release[edit]

Using Siteminder 6 - QMR5 with valid headers.

User is not created. Just shows the base page with my username up in the right corner. Check the database my user was never created. Any hints.

No hints at this time, but thanks for the warning. I'll attempt to install 1.13 sometime in the coming week to see what may have happened. --Vjg 22:42, 28 August 2008 (UTC)Reply
While I haven't done anything yet to update the code, I noted that the Shibboleth Authentication extension (to which Siteminder Authentication owes its heritage) has been updated to resolve this exact problem with MW 1.13. See the comments on Change Log for that extension. If you get to it before I do, that should help you get the issue corrected.--Vjg 15:08, 2 September 2008 (UTC)Reply

1.13 / 1.14[edit]

Any further work/testing done on this extension? I am planning to use it in 1.14.

Sadly, no, not by me. I no longer work on the web applications where I used this and don't have access to a testing environment that uses Siteminder. If I can't test, I'm not going to publish. Note that the code is very similar to the Shibboleth Authentication extension code, so anyone who is working in the proper environment should have little trouble updating the code. --Vjg 12:29, 24 March 2009 (UTC)Reply


  • Well I as able to fix the automatic login in 1.13/1.14, doesnt yet fix the user creation, but I dont need it for my setup
<?php
/**
 * Version 1.03 (Works out of box with MW 1.7 or above)
 *   - Works out with MW 1.15.1 (tested)
 *
 * Authentication Plugin for Siteminder
 * Derived from ShibAuthPlugin.php
 * Much of the commenting comes straight from AuthPlugin.php
 * Had to add return statements to several routines because a
 * return value is required from hook routines.
 *
 * Portions Copyright 2006, 2007 Regents of the University of California.
 * Portions Copyright 2007 Steven Langenaken
 * Released under the GNU General Public License
 *
 * Extension Maintainer:
 *         * Virgil Green <virgil.green AT bunge DOT com>
 * Extension Developers:
 *         * Virgil Green - Converted from Shibbeleth to Siteminder
 *
 * This extension assumes that the only method for signing on will
 * be SiteMinder. Local signon is not allowed. Since validation always
 * occurs before any part of the wiki is displayed, there are no
 * provisions made for selecting the style (local or Siteminder) and any
 * function that would be used for validation or synchronizatin is
 * set to simply return as though successful (or failure, if needed/appropriate).
 *
 * Suggested LocalSettings.php code
 *   ##Siteminder Authentication
 *   #Load SiteminderPlugin
 *   require_once('extensions/SiteminderAuthPlugin.php');
 *
 *   #Map data from Siteminder to local user data
 *   $siteminder_map_info = "true";
 *
 *   #Ssssh.... quiet down errors
 *   $olderror = error_reporting(E_ALL ^ E_NOTICE);
 *
 *   #Map Siteminder variables to extension variable
 *   # In this example, Siteminder is setting http headers named
 *   # full_name, user_name, and email when then appear in the $_SERVER array
 *   # in any of the other data collections that expose the headers to code.
 *   $siteminder_real_name = $_SERVER['HTTP_FULL_NAME'];
 *   $siteminder_user_name = ucfirst(strtolower($_SERVER['HTTP_USER_NAME']));
 *   $siteminder_email = $_SERVER['HTTP_EMAIL'];
 *
 *   #Siteminder logoff URL (uncomment and set proper URL if you want a logout link)
 *   #This is expected to be an abslute URL, including the protocol
 *   #$siteminder_logout = "<URL to Siteminder logout page>";
 *
 *   #Turn error reporting back on
 *   error_reporting($olderror);
 *
 *   #Activate Siteminder Plugin
 *   SetupSiteminderAuth();
 *
 */
 
require_once("$IP/includes/AuthPlugin.php");
 
class SiteminderAuthPlugin extends AuthPlugin {
	    var $existingUser = false;
 
        /**
         * Check whether there exists a user account with the given name.
         * The name will be normalized to MediaWiki's requirements, so
         * you might need to munge it (for instance, for lowercase initial
         * letters).
         *
         * @param string $username
         * @return bool
         * @access public
         */
        function userExists( $username ) {
                return true;
        }
        /**
         * Check if a username+password pair is a valid login.
         * The name will be normalized to MediaWiki's requirements, so
         * you might need to munge it (for instance, for lowercase initial
         * letters).
         *
         * @param string $username
         * @param string $password
         * @return bool
         * @access public
         */
        function authenticate( $username, $password) {
                global $siteminder_user_name;
 
                if($username == $siteminder_user_name)
                        return true;
                else
                        return false;
        }
 
        /**
         * Modify options in the login template.
         *
         * @param UserLoginTemplate $template
         * @access public
         */
        function modifyUITemplate( &$template ) {
                return;
        }
 
        /**
         * Set the domain this plugin is supposed to use when authenticating.
         *
         * @param string $domain
         * @access public
         */
        function setDomain( $domain ) {
                return;
        }
 
        /**
         * Check to see if the specific domain is a valid domain.
         *
         * @param string $domain
         * @return bool
         * @access 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
         * @access public
         */
        function updateUser( &$user ) {
                global $siteminder_map_info;
                global $siteminder_email;
                global $siteminder_real_name;
 
                if ($siteminder_map_info)
                {
                        if($siteminder_email != null)
                                $user->setEmail($siteminder_email);
                        if($siteminder_real_name != null)
                                $user->setRealName($siteminder_real_name);
                }
 
                //For security, set password to a non-existant hash.
                if($user->mPassword != "nologin")
                {
                        $user->mPassword = "nologin";
                        $user->saveSettings();
                }
 
                return true;
        }
 
 
        /**
         * Return true if 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.
         *
         * If you don't automatically create accounts, you must still create
         * accounts in some way. It's not possible to authenticate without
         * a local account.
         *
         * This is just a question, and shouldn't perform any actions.
         *
         * @return bool
         * @access public
         */
        function autoCreate() {
                return true;
        }
 
        /**
         * Can users change their passwords?
         *
         * @return bool
         */
        function allowPasswordChange() {
                global $siteminder_pretend;
                return $siteminder_pretend;
        }
 
        /**
         * Set the given password in the authentication database.
         * Return true if successful.
         *
         * @param string $password
         * @return bool
         * @access public
         */
        function setPassword( $password ) {
                global $siteminder_pretend;
                return $siteminder_pretend;
        }
 
        /**
         * Update user information in the external authentication database.
         * Return true if successful.
         *
         * @param User $user
         * @return bool
         * @access public
         */
        function updateExternalDB( $user ) {
                return true;
        }
 
        /**
         * Check to see if external accounts can be created.
         * Return true if external accounts can be created.
         * @return bool
         * @access public
         */
        function canCreateAccounts() {
                return false;
        }
 
        /**
         * Add a user to the external authentication database.
         * Return true if successful.
         *
         * @param User $user
         * @param string $password
         * @return bool
         * @access public
         */
        function addUser( $user, $password ) {
                return true;
        }
 
 
        /**
         * Return true to prevent logins that don't authenticate here from being
         * checked against the local database's password fields.
         *
         * This is just a question, and shouldn't perform any actions.
         *
         * @return bool
         * @access 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.
         *
         * The User object is passed by reference so it can be modified; don't
         * forget the & on your function declaration.
         *
         * @param User $user
         * @access public
         */
        function initUser( &$user ) {
                $this->updateUser($user);
        }
 
        /**
         * If you want to munge the case of an account name before the final
         * check, now is your chance.
         */
        function getCanonicalName( $username ) {
                return $username;
        }
}
 
function SiteminderGetAuthHook() {
	global $wgVersion;
				if (strcmp($wgVersion, "1.13") >= 0) {
								return 'UserLoadAfterLoadFromSession';
				} else {
								return 'AutoAuthenticate';
				}
}


/*
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
function SetupSiteMinderAuth()
{
        global $siteminder_user_name;
        global $wgHooks;
        global $wgAuth;
 
        if($siteminder_user_name != null)
        {																											   
           $wgHooks[SiteminderGetAuthHook()][] = "Siteminder".SiteminderGetAuthHook(); /* Hook for magical authN */  
           $wgHooks['PersonalUrls'][] = 'SiteminderSSOActive'; /* Disallow logout link */
           $wgAuth = new SiteminderAuthPlugin();
        }
}
 
/* Kill or replace logout link */
function SiteminderSSOActive(&$personal_urls, $title)
{
        global $siteminder_logout;
        global $siteminder_real_name;
        global $siteminder_map_info;
 
        if($siteminder_logout == null)
                $personal_urls['logout'] = null;
        else
                $personal_urls['logout']['href'] = $siteminder_logout;
 
        if($siteminder_real_name && $siteminder_map_info)
                $personal_urls['userpage']['text'] = $siteminder_real_name;
        return true;
}
function SiteminderAuthAuthenticate(&$user) {
				SiteminderShibUserLoadFromSession($user, true);
} 


/* Tries to be magical about when to log in users and when not to. */

function SiteminderUserLoadAfterLoadFromSession($user, $result)
{
        global $wgContLang;
        global $wgAuth;
        global $siteminder_user_name;
        global $wgHooks;
        global $siteminder_map_info;
        global $siteminder_pretend;
 
        SiteminderKillAA();
 
        //For versions of mediawiki which enjoy calling AutoAuth with null users
        if ($user === null) {
                $user = User::loadFromSession();
        }
 
        //They already with us?  If so, nix this function, we're good.
        if($user->isLoggedIn())
        {
                BringBackAA();
                return true;
        }
 
        //Is the user already in the database?
        if (User::idFromName($siteminder_user_name) != null)
        {					 

                $user = User::newFromName($siteminder_user_name);
                $smi = $siteminder_map_info;
                $siteminder_map_info = false;		
                $user->load();
				$wgAuth->existingUser = true;
                $wgAuth->updateUser($user); //Make sure password is nologin
                $siteminder_map_info = $smi;
                $user->SetupSession();
                $user->setCookies();
                return true;
        }
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //Okay, kick this up a notch then...
        $user->setName($wgContLang->ucfirst($siteminder_user_name));
 
        /*
         * Since we only get called when someone should be logged in, if they
         * aren't let's make that happen.  Oddly enough the way MW does all
         * this is simply to use a loginForm class that pretty much does
         * most of what you need.  Creating a loginform is a very very small
         * part of this object.
         */
        require_once("$IP/includes/specials/SpecialUserlogin.php");
 
        //This section contains a silly hack for MW
        global $wgLang;
        global $wgContLang;
        global $wgRequest;
        $wgLangUnset = false;
        if(!isset($wgLang))
        {
                $wgLang = $wgContLang;
                $wgLangUnset = true;
        }
 
        SiteminderKillAA();
 
        //This creates our form that'll do black magic
        $lf = new LoginForm($wgRequest);
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //And now we clean up our hack
        if($wgLangUnset == true)
        {
                unset($wgLang);
                unset($wgLangUnset);
        }
        //The mediawiki developers entirely broke use of this the
        //straightforward way in 1.9, so now we just lie...
        $siteminder_pretend = true; 

        //Now we _do_ the black magic
        $lf->mRemember = false;
        $user->loadDefaults($siteminder_user_name);
        $lf->initUser($user);
 
        //Stop pretending now
        $siteminder_pretend = false;

        //Finish it off
        $user->saveSettings();
        $user->setupSession();
        $user->setCookies();
        return true;
}


function SiteminderKillAA()
{
				global $wgHooks;
				global $wgAuth;
 
				//Temporarily kill The AutoAuth Hook to prevent recursion
				foreach ($wgHooks[SiteminderGetAuthHook()] as $key => $value)
				{	  

					if($value == "Siteminder".SiteminderGetAuthHook())
												
$wgHooks[SiteminderGetAuthHook()][$key] = 'BringBackAA';
				}
}

/* Puts the auto-auth hook back into the hooks array */
function BringBackAA()
{
        global $wgHooks;
        global $wgAuth;
 
        foreach ($wgHooks[SiteminderGetAuthHook()] as $key => $value)
        {
            if($value == 'BringBackAA')
                $wgHooks[SiteminderGetAuthHook()][$key] = "Siteminder".SiteminderGetAuthHook();
        }
        return true;
}
?>

Current State[edit]

Does anyone know if this extension is functional with MediaWiki 1.15.1 or later? Specifically, account creation.

Thanks,

--Enterprise user 20:37, 9 August 2010 (UTC)Reply


Finally got through Shibboleth authentication code and found that in addition, one needs to add "siteminder_pretend" global variable. If you look into the code, it is very obvious. Account creation now works. I tested in mediawiki 1.15.1

I inserted $siteminder_pretend in the Siteminder code anywhere $shib_pretend was present in the Shibboleth code, but auto-account creation still fails. I've verified that Siteminder HTTP headers are being retrieved correctly by the extension. Currently using MWv1.16.0.
How did you insert the $siteminder_pretend variable?
--Enterprise user 19:10, 14 September 2010 (UTC)Reply


Run on MediaWiki 1.16.2[edit]

  • I am using the above updated extension(Version 1.02) with MK 1.16.2, when loading the extension, I met the following errors:

Warning: Parameter 1 to SiteminderUserLoadAfterLoadFromSession() expected to be a reference, value given in D:\wamp\www\devmw\includes\Hooks.php on line 133 Detected bug in an extension! Hook SiteminderUserLoadAfterLoadFromSession failed to return a value; should return true to continue hook processing or false to abort. Backtrace:

  1. 0 D:\wamp\www\devmw\includes\User.php(266): wfRunHooks('UserLoadAfterLo...', Array)
  2. 1 D:\wamp\www\devmw\includes\User.php(3613): User->load()
  3. 2 D:\wamp\www\devmw\includes\User.php(1968): User->loadOptions()
  4. 3 [internal function]: User->getOption('numberheadings')
  5. 4 D:\wamp\www\devmw\includes\StubObject.php(58): call_user_func_array(Array, Array)
  6. 5 D:\wamp\www\devmw\includes\StubObject.php(182): StubObject->_call('getOption', Array)
  7. 6 [internal function]: StubUser->__call('getOption', Array)
  8. 7 D:\wamp\www\devmw\includes\parser\ParserOptions.php(150): StubUser->getOption('numberheadings')
  9. 8 D:\wamp\www\devmw\includes\parser\ParserOptions.php(109): ParserOptions->initialiseFromUser(Object(StubUser))
  10. 9 D:\wamp\www\devmw\includes\Article.php(4054): ParserOptions->__construct(Object(StubUser))
  11. 10 D:\wamp\www\devmw\includes\Article.php(745): Article->getParserOptions()
  12. 11 D:\wamp\www\devmw\includes\Wiki.php(493): Article->view()
  13. 12 D:\wamp\www\devmw\includes\Wiki.php(70): MediaWiki->performAction(Object(OutputPage), Object(Article), Object(Title), Object(User), Object(WebRequest))
  14. 13 D:\wamp\www\devmw\index.php(117): MediaWiki->performRequestForTitle(Object(Title), Object(Article), Object(OutputPage), Object(User), Object(WebRequest))
  15. 14 {main}

Anyone could help me? Thanks in advance!

Merged in changes, tested 1.23[edit]

I merged in some changes from the Shibboleth plugin, and one from LdapAuthentication. It's working for me on MediaWiki 1.23.8. I didn't touch (or read :) ) most of the comments, so they may no longer make sense. I also didn't test account creation yet. See the code below. Coordinatesystem (talk) 22:00, 9 March 2015 (UTC)Reply

I was getting errors like this when users without MW accounts logged in:

PHP Fatal error:  Cannot access protected property LoginForm::$mRemember

If I comment out this line: $lf->mRemember = false; - the autocreate works. I don't know exactly what this is for but I don't think it really matters since we're not using the login form in any situation anyway. I made the change below. Coordinatesystem (talk) 21:22, 17 March 2015 (UTC)Reply

<?php
/**
 * Version 1.1 (Works out of box with some versions > MW 1.7)
 *   - Works with MW 1.28.3 (partially tested)
 *
 * Authentication Plugin for Siteminder
 * Derived from ShibAuthPlugin.php
 * Much of the commenting comes straight from AuthPlugin.php
 * Had to add return statements to several routines because a
 * return value is required from hook routines.
 *
 * Portions Copyright 2006, 2007 Regents of the University of California.
 * Portions Copyright 2007 Steven Langenaken
 * Released under the GNU General Public License
 *
 * Extension Maintainer:
 *         * Virgil Green <virgil.green AT bunge DOT com>
 * Extension Developers:
 *         * Virgil Green - Converted from Shibbeleth to Siteminder
 *
 * This extension assumes that the only method for signing on will
 * be SiteMinder. Local signon is not allowed. Since validation always
 * occurs before any part of the wiki is displayed, there are no
 * provisions made for selecting the style (local or Siteminder) and any
 * function that would be used for validation or synchronizatin is
 * set to simply return as though successful (or failure, if needed/appropriate).
 *
 * Suggested LocalSettings.php code
 *   ##Siteminder Authentication
 *   #Load SiteminderPlugin
 *   require_once('extensions/SiteminderAuthPlugin.php');
 *
 *   #Map data from Siteminder to local user data
 *   $siteminder_map_info = "true";
 *
 *   #Ssssh.... quiet down errors
 *   $olderror = error_reporting(E_ALL ^ E_NOTICE);
 *
 *   #Map Siteminder variables to extension variable
 *   # In this example, Siteminder is setting http headers named
 *   # full_name, user_name, and email when then appear in the $_SERVER array
 *   # in any of the other data collections that expose the headers to code.
 *   $siteminder_real_name = $_SERVER['HTTP_FULL_NAME'];
 *   $siteminder_user_name = ucfirst(strtolower($_SERVER['HTTP_USER_NAME']));
 *   $siteminder_email = $_SERVER['HTTP_EMAIL'];
 *
 *   #Siteminder logoff URL (uncomment and set proper URL if you want a logout link)
 *   #This is expected to be an abslute URL, including the protocol
 *   #$siteminder_logout = "<URL to Siteminder logout page>";
 *
 *   #Turn error reporting back on
 *   error_reporting($olderror);
 *
 *   #Activate Siteminder Plugin
 *   SetupSiteminderAuth();
 *
 */
 
require_once("$IP/includes/AuthPlugin.php");
 
class SiteminderAuthPlugin extends AuthPlugin {
            var $existingUser = false;
 
        /**
         * Check whether there exists a user account with the given name.
         * The name will be normalized to MediaWiki's requirements, so
         * you might need to munge it (for instance, for lowercase initial
         * letters).
         *
         * @param string $username
         * @return bool
         * @access public
         */
        function userExists( $username ) {
                return true;
        }
        /**
         * Check if a username+password pair is a valid login.
         * The name will be normalized to MediaWiki's requirements, so
         * you might need to munge it (for instance, for lowercase initial
         * letters).
         *
         * @param string $username
         * @param string $password
         * @return bool
         * @access public
         */
        function authenticate( $username, $password) {
                global $siteminder_user_name;
 
                return $username == $siteminder_user_name;
        }
 
        /**
         * Modify options in the login template.
         *
         * @param UserLoginTemplate $template
         * @access public
         */
        function modifyUITemplate( &$template, &$type ) {
                return;
        }
 
        /**
         * Set the domain this plugin is supposed to use when authenticating.
         *
         * @param string $domain
         * @access public
         */
        function setDomain( $domain ) {
                return;
        }
 
        /**
         * Check to see if the specific domain is a valid domain.
         *
         * @param string $domain
         * @return bool
         * @access 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
         * @access public
         */
        function updateUser( &$user ) {
                global $siteminder_map_info;
                global $siteminder_email;
                global $siteminder_real_name;
 
                if ($siteminder_map_info)
                {
                        if($siteminder_email != null)
                                $user->setEmail($siteminder_email);
                        if($siteminder_real_name != null)
                                $user->setRealName($siteminder_real_name);
                }
 
                //For security, set password to a non-existant hash.
                if($user->mPassword != "nologin")
                {
                        $user->mPassword = "nologin";
                        $user->saveSettings();
                }
 
                return true;
        }
 
 
        /**
         * Return true if 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.
         *
         * If you don't automatically create accounts, you must still create
         * accounts in some way. It's not possible to authenticate without
         * a local account.
         *
         * This is just a question, and shouldn't perform any actions.
         *
         * @return bool
         * @access public
         */
        function autoCreate() {
                return true;
        }
 
        /**
         * Can users change their passwords?
         *
         * @return bool
         */
        function allowPasswordChange() {
                global $siteminder_pretend;
                return $siteminder_pretend;
        }
 
        /**
         * Set the given password in the authentication database.
         * Return true if successful.
         *
         * @param string $password
         * @return bool
         * @access public
         */
        function setPassword( $user, $password ) {
                global $siteminder_pretend;
                return $siteminder_pretend;
        }
 
        /**
         * Update user information in the external authentication database.
         * Return true if successful.
         *
         * @param User $user
         * @return bool
         * @access public
         */
        function updateExternalDB( $user ) {
                return true;
        }
 
        /**
         * Check to see if external accounts can be created.
         * Return true if external accounts can be created.
         * @return bool
         * @access public
         */
        function canCreateAccounts() {
                return false;
        }
 
        /**
         * Add a user to the external authentication database.
         * Return true if successful.
         *
         * @param User $user
         * @param string $password
         * @return bool
         * @access public
         */
        function addUser( $user, $password, $email = '', $realname = '' ) {
                return true;
        }
 
 
        /**
         * Return true to prevent logins that don't authenticate here from being
         * checked against the local database's password fields.
         *
         * This is just a question, and shouldn't perform any actions.
         *
         * @return bool
         * @access 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.
         *
         * The User object is passed by reference so it can be modified; don't
         * forget the & on your function declaration.
         *
         * @param User $user
         * @access public
         */
        function initUser( &$user, $autocreate = false ) {
                $this->updateUser($user);
        }
 
        /**
         * If you want to munge the case of an account name before the final
         * check, now is your chance.
         */
        function getCanonicalName( $username ) {
                return $username;
        }
}
 
function SiteminderGetAuthHook() {
        global $wgVersion;
                                if ($wgVersion >= "1.13") {
                                                                return 'UserLoadAfterLoadFromSession';
                                } else {
                                                                return 'AutoAuthenticate';
                                }
}


/*
 * End of AuthPlugin Code, beginning of hook code and auth functions
 */
function SetupSiteMinderAuth()
{
        global $siteminder_user_name;
        global $wgHooks;
        global $wgAuth;
 
        if($siteminder_user_name != null)
        {                                                                                                                                                                                                                          
           $wgHooks[SiteminderGetAuthHook()][] = "Siteminder".SiteminderGetAuthHook(); /* Hook for magical authN */  
           $wgHooks['PersonalUrls'][] = 'SiteminderSSOActive'; /* Disallow logout link */
           $wgAuth = new SiteminderAuthPlugin();
        }
}
 
/* Kill or replace logout link */
function SiteminderSSOActive(&$personal_urls, $title)
{
        global $siteminder_logout;
        global $siteminder_real_name;
        global $siteminder_map_info;
 
        if($siteminder_logout == null)
#                $personal_urls['logout'] = null;
                unset( $personal_urls['logout'] );
        else
                $personal_urls['logout']['href'] = $siteminder_logout;
 
        if($siteminder_real_name && $siteminder_map_info)
                $personal_urls['userpage']['text'] = $siteminder_real_name;
        return true;
}
function SiteminderAuthAuthenticate(&$user) {
                                SiteminderShibUserLoadFromSession($user, true);
} 


/* Tries to be magical about when to log in users and when not to. */

function SiteminderUserLoadAfterLoadFromSession($user)
{
        global $wgContLang;
        global $wgAuth;
        global $siteminder_user_name;
        global $wgHooks;
        global $siteminder_map_info;
        global $siteminder_pretend;
 
        SiteminderKillAA();
 
        //For versions of mediawiki which enjoy calling AutoAuth with null users
        if ($user === null) {
                $user = User::loadFromSession();
        }
 
        //They already with us?  If so, nix this function, we're good.
        if($user->isLoggedIn())
        {
                BringBackAA();
                return true;
        }
 
        //Is the user already in the database?
        if (User::idFromName($siteminder_user_name) != null)
        {                                        

                $user = User::newFromName($siteminder_user_name);
                $smi = $siteminder_map_info;
                $siteminder_map_info = false;           
                $user->load();
                                $wgAuth->existingUser = true;
                $wgAuth->updateUser($user); //Make sure password is nologin
                $siteminder_map_info = $smi;
                wfSetupSession();
                $user->setCookies();
                return true;
        }
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //Okay, kick this up a notch then...
        $user->setName($wgContLang->ucfirst($siteminder_user_name));
 
        /*
         * Since we only get called when someone should be logged in, if they
         * aren't let's make that happen.  Oddly enough the way MW does all
         * this is simply to use a loginForm class that pretty much does
         * most of what you need.  Creating a loginform is a very very small
         * part of this object.
         */
        require_once("$IP/includes/specials/SpecialUserlogin.php");
 
        //This section contains a silly hack for MW
        global $wgLang;
        global $wgContLang;
        global $wgRequest;
        $wgLangUnset = false;
        if(!isset($wgLang))
        {
                $wgLang = $wgContLang;
                $wgLangUnset = true;
        }
 
        SiteminderKillAA();
 
        //This creates our form that'll do black magic
        $lf = new LoginForm($wgRequest);
 
        //Place the hook back (Not strictly necessarily MW Ver >= 1.9)
        BringBackAA();
 
        //And now we clean up our hack
        if($wgLangUnset == true)
        {
                unset($wgLang);
                unset($wgLangUnset);
        }
        //The mediawiki developers entirely broke use of this the
        //straightforward way in 1.9, so now we just lie...
        $siteminder_pretend = true; 

        //Now we _do_ the black magic
        #$lf->mRemember = false;
        $user->loadDefaults($siteminder_user_name);
        $lf->initUser($user);
 
        //Stop pretending now
        $siteminder_pretend = false;

        //Finish it off
        $user->saveSettings();
        wfSetupSession();
        $user->setCookies();
        return true;
}


function SiteminderKillAA()
{
                                global $wgHooks;
                                global $wgAuth;
 
                                //Temporarily kill The AutoAuth Hook to prevent recursion
                                foreach ($wgHooks[SiteminderGetAuthHook()] as $key => $value)
                                {         

                                        if($value == "Siteminder".SiteminderGetAuthHook())
                                                                                                
$wgHooks[SiteminderGetAuthHook()][$key] = 'BringBackAA';
                                }
}

/* Puts the auto-auth hook back into the hooks array */
function BringBackAA()
{
        global $wgHooks;
        global $wgAuth;
 
        foreach ($wgHooks[SiteminderGetAuthHook()] as $key => $value)
        {
            if($value == 'BringBackAA')
                $wgHooks[SiteminderGetAuthHook()][$key] = "Siteminder".SiteminderGetAuthHook();
        }
        return true;
}
?>