Extension talk:SSL authentication

Working on integrating this into the LDAP Authentication plugin
This plugin is great, and exactly what I was looking for. I'll be integrating this into my LDAP Authentication plugin. I've been looking for documentation on how to do this for the past couple of weeks, but this plugin fits my need perfectly.

Thanks for the great work!

-- Ryan Lane

Little bug
Great work :), but when I enter my site first time in browsers session - I am not logged. The problem is probably in file SSLAuthPlugin.php in function SSLAuth:

SEARCH: //If exists, log them in   if($tmpuser->getID != 0) {       $wgUser = &$tmpuser; $wgUser->setCookies; $wgUser->setupSession; return; } REPLACE WITH: //If exists, log them in   if($tmpuser->getID != 0) {       $wgUser = &$tmpuser; $wgUser->setupSession; // Before cookies! $wgUser->setCookies; return; }

-- Krzysztof Kozlowski

tested with mediawiki 1.9?
Anyone else tried this out? I'm having a hell of a time getting it to work out.

Re - MediaWiki 1.9
Tested, but following changes were needed in SSLAuthPlugin.php: FIND: $tmpuser = User::LoadFromSession; REPLACE WITH: $tmpuser = new User ; $tmpuser->LoadFromSession; FIND: $tmpuser = User::newFromName($ssl_UN); REPLACE WITH: unset($tmpuser) ; $tmpuser = new User ; $tmpuser = $tmpuser->newFromName($ssl_UN);

And works OK

-- Krzysztof Kozlowski (kozik [some special char] kozik.net.pl)

1.9 better, but new error
Original exception: exception 'MWException' with message 'Unstub loop detected on call of $wgUser->getOption from StubUserLang::_newObject ' in /var/www/wiki/includes/StubObject.php:54

Note: Tested with 1.9.3
Succeded in integrating SSL authentication with the following SSLAuthPlugin.php:

<?php /** * Version 1.0.2 (Works out of box with MW 1.7.1 and up) * * Authentication Plugin for Apache2 mod_ssl * Derived from AuthPlugin.php and * http://meta.wikimedia.org/wiki/Shibboleth_Authentication * * Much of the commenting comes straight from AuthPlugin.php * * Portions Copyright 2006 Martin Johnson * Portions Copyright 2006, 2007 Regents of the University of California * Portions Copyright 2007 Steven Langenaken * Released under the GNU General Public License * * Changes between 1.0.2 and 1.0.1: * = Merge changes from Shibboleth Authentication: (By DJC) * == More 1.9 compatibility fixes and less ugly code * * Changes between 1.0.1 and 1.0: * = Merge changes from Shibboleth Authentication: (By DJC) * == Compatible with MW 1.9+ again (By DJC) * == Minor fix in loginform handling (By Steven Langenaken) * * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication */ require_once('AuthPlugin.php'); class SSLAuthPlugin extends AuthPlugin { /**     * See AuthPlugin.php for specific information */    function userExists( $username ) { return true; }    /**      * See AuthPlugin.php for specific information */    function authenticate( $username, $password ) { global $ssl_UN; if($username == $ssl_UN) return true; else return false; }    /**      * See AuthPlugin.php for specific information */    function modifyUITemplate( &$template ) { $template->set( 'usedomain', false ); }    /**      * See AuthPlugin.php for specific information */    function setDomain( $domain ) { $this->domain = $domain; }    /**      * See AuthPlugin.php for specific information */    function validDomain( $domain ) { return true; }    /**      * See AuthPlugin.php for specific information */    function updateUser( &$user ) { global $ssl_map_info; global $ssl_email; global $ssl_RN; //Map extra info or not? if($ssl_map_info != true) {                    //If Email, set info in MW             if($ssl_email != null) $user->setEmail($ssl_email); //If realName, set info in MW            if($ssl_RN != null) $user->setRealName($ssl_RN); }       //For security, set password to a non-existant hash. $user->load; if($user->mPassword != "nologin") {           $user->mPassword = "nologin"; $user->saveSettings; }        return true; }    /**      * See AuthPlugin.php for specific information */    function autoCreate { return true; }    /**      * See AuthPlugin.php for specific information */   //function allowPasswordChange { //   return false; //}

function allowPasswordChange { return true; // KK - bug: password-change-forbidden }

/**     * See AuthPlugin.php for specific information */   function setPassword( $password ) { return false; }    /**      * See AuthPlugin.php for specific information */    function updateExternalDB( $user ) { //Not really, but wiki thinks we did... return true; }    /**      * See AuthPlugin.php for specific information */    function canCreateAccounts { return false; }    /**      * See AuthPlugin.php for specific information */    function addUser( $user, $password ) { return false; }    /**      * See AuthPlugin.php for specific information */    function strict { return false; }    /**      * See AuthPlugin.php for specific information */    function initUser( &$user ) { //Update MW with new user information $this->updateUser($user); }    /**      * See AuthPlugin.php for specific information */    function getCanonicalName( $username ) { return $username; } } /** * End of AuthPlugin Code, beginning of hook code and auth functions */ /** * Some extension information init */ $wgExtensionFunctions[] = 'SSLAuthSetup'; $wgExtensionCredits['other'][] = array(   'name' => 'SSLAuth',    'version' => '1.0.2',    'author' => 'Martin Johnson',    'description' => 'Automagic login with certificates using Apache2 mod_ssl clientside',    'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication' ); /** * Setup extensionfunctions */ function SSLAuthSetup {    global $ssl_UN; global $wgHooks; global $wgAuth; if($ssl_UN != null) {        $wgHooks['AutoAuthenticate'][] = 'SSLAuth'; /* Hook for magical authN */ $wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */ $wgAuth = new SSLAuthPlugin; } /** * Hooks looks funny in Special:Version * Written twice. Whats wrong with this code? */ } /* No logout link in MW */ function NoLogout(&$personal_urls, $title) {    $personal_urls['logout'] = null; } /* Tries to be magical about when to log in users and when not to. */ function SSLAuth(&$user) {    global $ssl_UN; global $wgUser; global $wgContLang; global $wgHooks;

//Give us a user, see if we're around //$tmpuser = User::LoadFromSession; // Pre MediaWiki 1.10 $tmpuser = new User ; $tmpuser->LoadFromSession;

//$tmpuser = User::newFromSession; // For MediaWiki 1.10.0 and up    //They already with us? If so, quit this function. if($tmpuser->isLoggedIn) return; //Is the user already in the database? //$tmpuser = User::newFromName($ssl_UN); unset($tmpuser) ; $tmpuser = new User ; $tmpuser = $tmpuser->newFromName($ssl_UN);

//If exists, log them in    if($tmpuser->getID != 0) {        $wgUser = &$tmpuser; $wgUser->setupSession; $wgUser->setCookies; return; }    //Okay, kick this up a notch then... //$wgUser = &$tmpuser; $wgUser = new User;

$wgUser->setName($wgContLang->ucfirst($ssl_UN)); /*     * Some magic that Shibboleth Authentication does and I just copy */     require_once('SpecialUserlogin.php'); //This section contains a silly hack for MW     global $wgLang; global $wgContLang; global $wgRequest; if(!isset($wgLang)) {         $wgLang = $wgContLang; $wgLangUnset = true; }     //Temporarily kill The AutoAuth Hook to prevent recursion foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {           if($value == 'AutoAuth') $wgHooks['AutoAuthenticate'][$key] = 'BringBackAA'; }     //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); }

//Now we _do_ the black magic $lf->mRemember = false; $lf->initUser($wgUser); //Finish it off $wgUser->saveSettings; $wgUser->setupSession; $wgUser->setCookies; }

/* Puts the auto-auth hook back into the hooks array */ function BringBackAA {       global $wgHooks;

foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {           if($value == 'BringBackAA') $wgHooks['AutoAuthenticate'][$key] = 'AutoAuth'; } }

?>

Regards

Markus

gridsitewiki
Is it worth investigating if the work done for x509 integration with 1.4.x tree as part of GridSiteWiki can be reused?

Internal error :
Hi , Got an internal error when trying to use the extension :

MediaWiki internal error. Original exception: exception 'MWException' with message 'Unstub loop detected on call of $wgUser->getOption from StubUserLang::_newObject ' in /var/www/html/wiki/includes/StubObject.php:54 Stack trace:
 * 1) 0 /var/www/html/wiki/includes/StubObject.php(31): StubObject->_unstub('getOption', 5)
 * 2) 1 /var/www/html/wiki/includes/StubObject.php(122): StubObject->_call('getOption', Array)
 * 3) 2 [internal function]: StubUser->__call('getOption', Array)
 * 4) 3 /var/www/html/wiki/includes/StubObject.php(92): StubUser->getOption('language')
 * 5) 4 /var/www/html/wiki/includes/StubObject.php(57): StubUserLang->_newObject
 * 6) 5 /var/www/html/wiki/includes/StubObject.php(31): StubObject->_unstub('specialPage', 5)
 * 7) 6 /var/www/html/wiki/includes/StubObject.php(87): StubObject->_call('specialPage', Array)
 * 8) 7 [internal function]: StubUserLang->__call('specialPage', Array)
 * 9) 8 /var/www/html/wiki/includes/SpecialUserlogin.php(83): StubUserLang->specialPage('Userlogout')
 * 10) 9 /var/www/html/wiki/extensions/SSLAuthPlugin.php(268): LoginForm->LoginForm(Object(WebRequest))
 * 11) 10 [internal function]: SSLAuth(Object(User))
 * 12) 11 /var/www/html/wiki/includes/Hooks.php(113): call_user_func_array('SSLAuth', Array)
 * 13) 12 /var/www/html/wiki/includes/StubObject.php(131): wfRunHooks('AutoAuthenticat...', Array)
 * 14) 13 /var/www/html/wiki/includes/StubObject.php(57): StubUser->_newObject
 * 15) 14 /var/www/html/wiki/includes/StubObject.php(31): StubObject->_unstub('getOption', 5)
 * 16) 15 /var/www/html/wiki/includes/StubObject.php(122): StubObject->_call('getOption', Array)
 * 17) 16 [internal function]: StubUser->__call('getOption', Array)
 * 18) 17 /var/www/html/wiki/includes/StubObject.php(92): StubUser->getOption('language')
 * 19) 18 /var/www/html/wiki/includes/StubObject.php(57): StubUserLang->_newObject
 * 20) 19 /var/www/html/wiki/includes/StubObject.php(31): StubObject->_unstub('specialPage', 5)
 * 21) 20 /var/www/html/wiki/includes/StubObject.php(87): StubObject->_call('specialPage', Array)
 * 22) 21 [internal function]: StubUserLang->__call('specialPage', Array)
 * 23) 22 /var/www/html/wiki/includes/SpecialUserlogin.php(83): StubUserLang->specialPage('Userlogout')
 * 24) 23 /var/www/html/wiki/extensions/SSLAuthPlugin.php(268): LoginForm->LoginForm(Object(WebRequest))
 * 25) 24 [internal function]: SSLAuth(Object(User))
 * 26) 25 /var/www/html/wiki/includes/Hooks.php(113): call_user_func_array('SSLAuth', Array)
 * 27) 26 /var/www/html/wiki/includes/StubObject.php(131): wfRunHooks('AutoAuthenticat...', Array)
 * 28) 27 /var/www/html/wiki/includes/StubObject.php(57): StubUser->_newObject
 * 29) 28 /var/www/html/wiki/includes/StubObject.php(31): StubObject->_unstub('isAllowed', 5)
 * 30) 29 /var/www/html/wiki/includes/StubObject.php(122): StubObject->_call('isAllowed', Array)
 * 31) 30 [internal function]: StubUser->__call('isAllowed', Array)
 * 32) 31 /var/www/html/wiki/includes/Title.php(1144): StubUser->isAllowed('read')
 * 33) 32 /var/www/html/wiki/includes/Wiki.php(123): Title->userCanRead
 * 34) 33 /var/www/html/wiki/includes/Wiki.php(43): MediaWiki->preliminaryChecks(Object(Title), Object(StubObject), Object(WebRequest))
 * 35) 34 /var/www/html/wiki/index.php(89): MediaWiki->initialize(Object(Title), Object(StubObject), Object(StubUser), Object(WebRequest))
 * 36) 35 {main}

Exception caught inside exception handler: exception 'MWException' with message 'Unstub loop detected on call of $wgLang->getCode  from MessageCache::get ' in /var/www/html/wiki/includes/StubObject.php:54 Stack trace:
 * 1) 0 /var/www/html/wiki/includes/StubObject.php(31): StubObject->_unstub('getCode', 5)
 * 2) 1 /var/www/html/wiki/includes/StubObject.php(87): StubObject->_call('getCode', Array)
 * 3) 2 [internal function]: StubUserLang->__call('getCode', Array)
 * 4) 3 /var/www/html/wiki/includes/MessageCache.php(433): StubUserLang->getCode
 * 5) 4 /var/www/html/wiki/includes/GlobalFunctions.php(463): MessageCache->get('internalerror', true, false)
 * 6) 5 /var/www/html/wiki/includes/GlobalFunctions.php(421): wfMsgGetKey('internalerror', true, false, true)
 * 7) 6 /var/www/html/wiki/includes/GlobalFunctions.php(326): wfMsgReal('internalerror', Array, true)
 * 8) 7 /var/www/html/wiki/includes/Exception.php(57): wfMsg('internalerror')
 * 9) 8 /var/www/html/wiki/includes/Exception.php(125): MWException->getPageTitle
 * 10) 9 /var/www/html/wiki/includes/Exception.php(88): MWException->htmlHeader
 * 11) 10 /var/www/html/wiki/includes/Exception.php(111): MWException->reportHTML
 * 12) 11 /var/www/html/wiki/includes/Exception.php(191): MWException->report
 * 13) 12 /var/www/html/wiki/includes/Exception.php(225): wfReportException(Object(MWException))
 * 14) 13 [internal function]: wfExceptionHandler(Object(MWException))
 * 15) 14 {main}

In my LocalSetting.php :

# #
 * 1) SSL Authentication Stuff

require_once('extensions/SSLAuthPlugin.php');
 * 1) Load SSLAuthPlugin

$ssl_map_info = "true";
 * 1) Feel free to use extra PHP code to munge the variables if you'd like
 * 2) Additionally if you wish to only map some of the name data, set this to true
 * 3) and either blank ssl_RN and ssl_email or comment them out entirely.

$olderror = error_reporting(E_ALL ^ E_NOTICE);
 * 1) Ssssh.... quiet down errors

$ssl_RN = strtolower($_SERVER['SSL_CLIENT_S_DN_CN']);
 * 1) Map Real Name from certificate
 * 2) Can be DN but is it right?


 * 1) MW username is required to map to something
 * 2) You should beware of possible namespace collisions, it is best to chose
 * 3) something that will not violate MW's usual restrictions on characters

$search = array ('/Ã¥/i', '/Ã¤/i', '/Ã¶/i', '/Ã©/i'); $replace = array ('a', 'a', 'o', 'e');
 * 1) Just using Firstname + Lastname from Certificate 'will' make collisions... but what to use?
 * 2) UN could be md5-hash of DN, but its ugly to use...

$nom = explode(" ",$_SERVER['SSL_CLIENT_S_DN_CN']);

$firstname = $nom[0]; $firstname = preg_replace($search, $replace, $firstname);

$lastname = $nom[1]; $lastname = preg_replace($search, $replace, $lastname);

$ssl_UN = $_SERVER['SSL_CLIENT_S_DN_Email'];

$ssl_email = $_SERVER['SSL_CLIENT_S_DN_Email'];
 * 1) Map e-mail to something close?

error_reporting($olderror);
 * 1) Turn error reporting back on

SSLAuthSetup;
 * 1) Activate SSL Plugin

i've just modify some variables to be working with my AC. Did you have any Idea ? Thanks

Bug?
When I install the extension as advised, I got the following error in Apache's error_log:

[Wed May 30 08:26:57 2007] [error] [client 127.0.0.2] PHP Fatal error: Call to undefined method User::newfromsession in /srv/www/htdocs/mediawiki/extensions/SSLAuthPlugin.php on line 223

My MediaWiki version is 1.8.2 and my PHP version is 5.2.0 on openSuSE 10.2.

Thanks for any hint

-- Uwe 07:31, 30 May 2007 (UTC)

Work in progress
Hi,

No work has been done from me the last time but now I'm back. I have noticed that MediaWiki 1.10.0 and Extension:SSL authentication don't work so well, actually not at all... Djcapelis, Krzysztof Kozlowski, Markus and others has contibuted in the past. Thanks! If you, or someone else has more tips or solutions, please help. I use MeliaWiki 1.7.1 at work but its time to upgrade. :-)

SSL auth and MediaWiki 1.10.0
Problem - with "Internal error :" replace if($value == 'AutoAuth') (...) $wgHooks['AutoAuthenticate'][$key] = 'AutoAuth'; with if($value == 'SSLAuth') (...) $wgHooks['AutoAuthenticate'][$key] = 'SSLAuth';

Krzysztof Kozłowski --217.153.130.210 12:07, 12 June 2007 (UTC)

SSL Auth and MediaWiki 1.10.0 - new version
Tested with 1.10.0 and works OK but I haven't done many tests (simple usage, auto-login, etc.). Probably wont work with 1.7 and 1.8 (<1.10). Previous error: Original exception: exception 'MWException' with message 'Unstub loop detected on call of $wgUser->getOption from StubUserLang::_newObject (when user did not exist in database) has been fixed.

<?php /** * Version 1.0.2 (Works out of box with MW 1.7.1 and up) * * Authentication Plugin for Apache2 mod_ssl * Derived from AuthPlugin.php and * http://meta.wikimedia.org/wiki/Shibboleth_Authentication * * Much of the commenting comes straight from AuthPlugin.php * * Portions Copyright 2006 Martin Johnson * Portions Copyright 2006, 2007 Regents of the University of California * Portions Copyright 2007 Steven Langenaken * Released under the GNU General Public License * * Changes between 1.0.2 and 1.0.1: * = Merge changes from Shibboleth Authentication: (By DJC) * == More 1.9 compatibility fixes and less ugly code * * Changes between 1.0.1 and 1.0: * = Merge changes from Shibboleth Authentication: (By DJC) * == Compatible with MW 1.9+ again (By DJC) * == Minor fix in loginform handling (By Steven Langenaken) * * Documentation at http://www.mediawiki.org/wiki/Extension:SSL_authentication */ require_once('AuthPlugin.php'); class SSLAuthPlugin extends AuthPlugin { /**     * See AuthPlugin.php for specific information */    function userExists( $username ) { return true; }    /**      * See AuthPlugin.php for specific information */    function authenticate( $username, $password ) { global $ssl_UN; if($username == $ssl_UN) return true; else return false; }    /**      * See AuthPlugin.php for specific information */    function modifyUITemplate( &$template ) { $template->set( 'usedomain', false ); }    /**      * See AuthPlugin.php for specific information */    function setDomain( $domain ) { $this->domain = $domain; }    /**      * See AuthPlugin.php for specific information */    function validDomain( $domain ) { return true; }    /**      * See AuthPlugin.php for specific information */    function updateUser( &$user ) { global $ssl_map_info; global $ssl_email; global $ssl_RN; //Map extra info or not? if($ssl_map_info) {                    //If Email, set info in MW             if($ssl_email) $user->setEmail($ssl_email); //If realName, set info in MW            if($ssl_RN) $user->setRealName($ssl_RN); }       // KK - MediaWiki 1.10.0 $user->setInternalPassword(mt_rand . mt_rand) ; return true; }    /**      * See AuthPlugin.php for specific information */    function autoCreate { return true; }    /**      * See AuthPlugin.php for specific information */   function allowPasswordChange { return false; }

/**     * See AuthPlugin.php for specific information */   function setPassword( $password ) { return false; }    /**      * See AuthPlugin.php for specific information */    function updateExternalDB( $user ) { //Not really, but wiki thinks we did... return true; }    /**      * See AuthPlugin.php for specific information */    function canCreateAccounts { return false; }    /**      * See AuthPlugin.php for specific information */    function addUser( $user, $password ) { return false; }    /**      * See AuthPlugin.php for specific information */    function strict { return false; }    /**      * See AuthPlugin.php for specific information */    function initUser( &$user ) { //Update MW with new user information $this->updateUser($user); }    /**      * See AuthPlugin.php for specific information */    function getCanonicalName( $username ) { return $username; } } /** * End of AuthPlugin Code, beginning of hook code and auth functions */ /** * Some extension information init */ $wgExtensionFunctions[] = 'SSLAuthSetup'; $wgExtensionCredits['other'][] = array(   'name' => 'SSLAuth',    'version' => '1.0.2',    'author' => 'Martin Johnson',    'description' => 'Automagic login with certificates using Apache2 mod_ssl clientside',    'url' => 'http://www.mediawiki.org/wiki/Extension:SSL_authentication' ); /** * Setup extensionfunctions */ function SSLAuthSetup {    global $ssl_UN; global $wgHooks; global $wgAuth; if($ssl_UN != null) {        $wgHooks['AutoAuthenticate'][] = 'SSLAuth'; /* Hook for magical authN */ $wgHooks['PersonalUrls'][] = 'NoLogout'; /* Disallow logout link */ $wgAuth = new SSLAuthPlugin; } /** * Hooks looks funny in Special:Version * Written twice. Whats wrong with this code? */ } /* No logout link in MW */ function NoLogout(&$personal_urls, $title) {    $personal_urls['logout'] = null; } /* Tries to be magical about when to log in users and when not to. */ function SSLAuth(&$user) {    global $ssl_UN; global $wgUser; global $wgContLang; global $wgHooks;

//Temporarily kill The AutoAuth Hook to prevent recursion foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {     if($value == 'SSLAuth') $wgHooks['AutoAuthenticate'][$key] = 'BringBackAA'; }   //Give us a user, see if we're around //$tmpuser = User::LoadFromSession; // MediaWiki < 1.10 $tmpuser = User::newFromSession;// MediaWiki 1.10.0 and up

//They already with us? If so, quit this function. if($tmpuser->isLoggedIn) {        BringBackAA; return; }

//Is the user already in the database? $tmpuser = User::newFromName($ssl_UN) ; //If exists, log them in    if($tmpuser->getID) {         $wgUser = &$tmpuser; $user = &$tmpuser; $user->setupSession; // Session before cookies! $user->setCookies; return; }    //Place the hook back (Not strictly necessarily MW Ver >= 1.9) BringBackAA;

//Okay, kick this up a notch then... $user = &$tmpuser; $user->setName($ssl_UN); // Set users name - Dont use ucfirst...

/*     * Some magic that Shibboleth Authentication does and I just copy */     require_once('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; }     //Temporarily kill The AutoAuth Hook to prevent recursion foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {       if($value == 'SSLAuth') $wgHooks['AutoAuthenticate'][$key] = 'BringBackAA'; }

//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); }

//Now we _do_ the black magic $lf->mRemember = false; $lf->initUser($user); //Finish it off $user->saveSettings; $user->setupSession; $user->setCookies; }

/* Puts the auto-auth hook back into the hooks array */ function BringBackAA {       global $wgHooks;

foreach ($wgHooks['AutoAuthenticate'] as $key => $value) {           if($value == 'BringBackAA') $wgHooks['AutoAuthenticate'][$key] = 'SSLAuth'; } }

?>

Krzysztof Kozlowski --217.153.130.210 13:04, 12 June 2007 (UTC)