Extension:QISSingleSignOn
From MediaWiki.org
|
QISSingleSignOn Release status: stable |
|||
|---|---|---|---|
| Implementation | User identity | ||
| Description | Single Sign On from HISQIS-Portal | ||
| Author(s) | Hendrik BrummermannTalk | ||
| Last Version | 0.4 | ||
| MediaWiki | 1.6 or newer | ||
| License | CC-BY / GPL | ||
| Download | see below | ||
|
|||
[edit] Purpose
Coordinates user authentication with an HISQIS portal (HISQIS is a software used by many German universities to offer campus services).
<?php2 // Change Log // ========== // 0.4 2008-09-12: support for MediaWiki 1.13 [[de:Benutzer:Hendrik Brummermann]] // 0.3 2006-05-14: support for AutoAuth-hook on MW 1.6 (fixes returnto-problem and removes the redirect page) // 0.2 2006-05-07: added support for _ridlist [[de:Benutzer:Hendrik Brummermann]] // 0.1.3 2005-08-29: added to Special:Version [[de:Benutzer:Hendrik Brummermann]] // 0.1.2 2005-08-13: urldecode username token [[de:Benutzer:Hendrik Brummermann]] // 0.1.1 2005-05-20: Fixed timeout check [[de:Benutzer:Hendrik Brummermann]] // 0.1 2005-05-18: First version [[de:Benutzer:Hendrik Brummermann]] /** * This plugin allows MediaWiki to be part of a single sign on environment. * * * Installation * ============ * - Copy QISSingleSignOn.php (this file) into the extension folder * - Add this to your LocalSettings.php: * require_once($IP."/extensions/QISSingleSignOn.php"); * $wgAuthQISSingleSignOnSharedSecret = 'kahC1oo3pieg6FaekEhou1aipEivae4fe'; // replace with random characters * $wgAuthQISSingleSignOnService = 'wiki'; * $wgAuth = new QISSingleSignOn(); * * * Linking the authentication server and MediaWiki * =============================================== * * MediaWiki 1.6 * ============= * Create a link to http://example.com/mediawiki/index.php/Main_Page?qisssotoken= * 1.0/1115814654/wik/schmidt/d1bf93299de1b68e6d382c893bf1215f (one line). In this * example Main_Page is the name of the page you want to link to and qissotoken * is the authentication token described below. * * MediaWiki 1.3 - 1.5 * =================== * The authentication server has to create a token for MediaWiki and * transmit it as "password": * * action="/mediawiki/index.php?title=Spezial:Userlogin&action=submit&returnto=Main_Page" * wpLoginattempt=Anmelden * wpName=username * wpPassword=1.0/1115814654/wik/schmidt/d1bf93299de1b68e6d382c893bf1215f * * You must put this variables into a hidden form because MediaWiki will * only accept POST-requests. This form can be triggered automatically * by JavaScript: * <body onload="document.forms[0].submit();"> * * * Details On The Required Token * ============================= * * The token look lines this (without spaces): * * 1.0 / 1115814654 / wiki / schmidt / d1bf93299de1b68e6d382c893bf1215f * version / time / service / user / hash * * The second parameter is is the token creation time measured in the * number of seconds since the Unix Epoch (0:00:00 January 1, 1970 GMT). * The third token is the name of the destination service as configured in * the $wgAuthQISSingleSignOnService option in your LocalSettings.php. * The forth token is the user name. * * A shared secret is added to theses parameters and the md5 hash is * calculated. This hash is used to verify the the token has not been * manipulated or forged. The shared secret is only known to the * authentication server and your MediaWiki installation * ($wgAuthQISSingleSignOnSharedSecret in LocalSettings.php). * Without the knowledge of the shared secret it is impossible to * calculate the correct hash. * * Please note that the separation of user and hash is not the 4th slash * but the last one. (The user name may contain '/'-chars). */ # This file is based upon a work CC-BY Hendrik Brummermann <nhb_web@nexgo.de>. # As it must implement a GPLed interface, however, it becomes GPL: # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # http://www.gnu.org/copyleft/gpl.html require_once($IP."/includes/AuthPlugin.php"); /** * Authentication plugin using QISSingleSignOn. */ class QISSingleSignOn extends AuthPlugin { function userExists( $username ) { return true; // We cannot answer this question without the token } /** * Check the configuration options * * @access private */ function checkConfiguration() { global $wgAuthQISSingleSignOnSharedSecret, $wgAuthQISSingleSignOnService; if (!isset($wgAuthQISSingleSignOnSharedSecret)) { wfDebugDieBacktrace('QISSingleSignOn: $wgAuthQISSingleSignOnSharedSecret undefined in LocalSettings.php.'); } if (!isset($wgAuthQISSingleSignOnService)) { wfDebugDieBacktrace('QISSingleSignOn: $wgAuthQISSingleSignOnService undefined in LocalSettings.php.'); } } function authenticate( $username, $password ) { $user = $this->verifyToken($password); if ($user == null) { // ungueltiges Token wfDebug('QISSingleSignOn: Ungueltiges Token'); return false; } // Stimmt der angegebene username und die Benutzerinformation ueberein if ($user != $username) { wfDebug('QISSingleSignOn: Invalid user name:'.htmlspecialchars($token)); return false; } return true; } function verifyToken($token) { global $wgAuthQISSingleSignOnService, $wgAuthQISSingleSignOnSharedSecret; // check the configuration options in LocalSettings.php QISSingleSignOn::checkConfiguration(); wfDebug('QISSingleSignOn: token:'.htmlspecialchars($token)); // prepare token $tokens = explode('/', $token, 4); if ((count($tokens) != 4) or (strpos($tokens[3], '/') === false)) { wfDebug('QISSingleSignOn: Token incomplete:'.htmlspecialchars($token)); return null; } // find the _last_ '/' to split username and hash as the username may include '/'-chars. $temp_pos = strrpos($tokens[3], '/'); $tokens[4] = substr($tokens[3], $temp_pos + 1); $tokens[3] = substr($tokens[3], 0, $temp_pos); // check version if ($tokens[0] != '1.0') { wfDebug('QISSingleSignOn: Unknown version:'.htmlspecialchars($tokens)); return null; } // check time $currentTime = microtime(); $currentTime = substr($currentTime, strpos($currentTime, ' ')); if (intval($tokens[1]) > intval($currentTime) + 60) { wfDebug('QISSingleSignOn: Token was created in the future (Check your clocks):'.htmlspecialchars($token)); return null; } if (intval($tokens[1]) + 60 < intval($currentTime)) { wfDebug('QISSingleSignOn: Token expired:'.htmlspecialchars($token)); return null; } // check service name if ($tokens[2] != $wgAuthQISSingleSignOnService) { wfDebug('QISSingleSignOn: Wrong service:'.htmlspecialchars($token)); return null; } // check username name (using Title::newFormText as in User::newFromName) $userinfo = explode('/', urldecode($tokens[3])); // Andere Methode wie bei tokens: find the _last_ '/' to split username and hash as the username may include '/'-chars. // $temp_pos = strrpos($tokens[3], '/'); // $userinfo[1] = substr($tokens[3], $temp_pos + 1); // $userinfo[0] = substr($tokens[3], 0, $temp_pos); // wfDebug('QISSingleSignOn: userinfo-0:'.$userinfo[0]."\n"); // wfDebug('QISSingleSignOn: userinfo-1:'.$userinfo[1]."\n"); $t = Title::newFromText($userinfo[0]); if ($t == null) { wfDebug('QISSingleSignOn: Invalid character in user name: '.htmlspecialchars($userinfo[0])); return null; } $user = $t->getText(); // check hash $toHash = $tokens[0].'/'.$tokens[1].'/'.$tokens[2].'/'.$tokens[3].'/'.$wgAuthQISSingleSignOnSharedSecret; $hash = md5($toHash); if ($hash != $tokens[4]) { wfDebug('QISSingleSignOn: Hash verification failed:'.htmlspecialchars($token).' Should be: ' . $hash); return null; } // copy _ridlist to session for WikiRights (if present) if (count($userinfo) > -1) { session_start(); $_SESSION['_ridlist'] = $userinfo[1]; } // welcome, you passed all tests. return $user; } function autoCreate() { return true; } function strict() { return false; } function initUser( &$user ) { # Override this to do something. // TODO: email // TODO: groups, rights } } function myInitUser (&$user) { $u->addToDatabase(); $u->setToken(); return $u; } function QISSingleSignOnAutoAuthenticate(&$user) { global $wgRequest; /* if ( $user != null) { // user is authenticated (by another hook) return true; } */ $token = $wgRequest->getVal("qisssotoken"); if ( $token != null ) { $username = QISSingleSignOn::verifyToken($token); if ( $username != null) { $u = User::newFromName( $username ); if ( 0 == $u->getID() ) { if ( QISSingleSignOn::autoCreate() && QISSingleSignOn::userExists( $username ) ) { $u->addToDatabase(); $u->setToken(); } } $user = $u; $u->setCookies(); } } return true; } function QISSingleSignOnUserLoadFromSession($user, &$result) { global $wgRequest; $token = $wgRequest->getVal("qisssotoken"); if ( $token != null ) { $username = QISSingleSignOn::verifyToken($token); if ( $username != null) { $u = User::newFromName( $username ); if ( 0 == $u->getID() ) { if ( QISSingleSignOn::autoCreate() && QISSingleSignOn::userExists( $username ) ) { $u->addToDatabase(); $u->setToken(); } } $localId = User::idFromName( $username ); if ( !$localId ) { return true; } else { $user->setID( $localId ); $user->loadFromId(); } $result = true; $user->setCookies(); wfSetupSession(); } } return true; } function QISSingleSignOnUserLogout(&$user) { session_start(); $_SESSION['_ridlist'] = null; return false; } $wgHooks['UserLogoutComplete'][] = 'QISSingleSignOnUserLogout'; $wgHooks['AutoAuthenticate'][] = 'QISSingleSignOnAutoAuthenticate'; $wgHooks['UserLoadFromSession'][] = 'QISSingleSignOnUserLoadFromSession'; $wgExtensionCredits['other'][] = array( 'name' => 'QISSingleSignOn ', 'version' => '0.4', 'author' => 'Hendrik Brummermann', 'url' => 'http://www.mediawiki.org/wiki/Extension:QISSingleSignOn', 'description' => 'Single Sign On from HISQIS-Portal' ); ?>

