Extension:AutomaticCAS USER
From MediaWiki.org
|
Automatic CAS Authentication Release status: beta |
|
|---|---|
| Implementation | User identity |
| Description | Automatically logs users using CAS Server. Also, a Single sign out is configurable. |
| Author(s) | Ramon Perez, iEcolab |
| Last version | 1.0 |
| MediaWiki | 1.9 or later |
| License | GPLv2 |
| Download | see below |
| Check usage and version matrix | |
Automatic CAS Authentication extension automatically logs users using the CAS Server. It is possible to do a single sign out configuration.
Save the file as /extensions/Auth_cas/Auth_cas.php
Download phpCAS library and save in /extensions/Auth_cas. So, you can download a package with all files in iEcolab
Then place the following two lines in your LocalSettings.php file:
require_once('extensions/Auth_cas/Auth_cas.php'); $wgAuth = new Auth_cas();
Note: Using this extension sets $wgMinimalPasswordLength to zero
Code [edit]
<?php // // 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, see <http://www.gnu.org/licenses/>. // // Copyright 2010 Ramon Perez // // In 2009, the copyright holders determined that the original publishing of this code // under GPLv3 was legally and logistically in error, and re-licensed it under GPLv2. // // See http://www.mediawiki.org/wiki/Extension:AutomaticCAS_USER // // Adapted by Rusty (REMOTE_USER) to do a CAS Authentication for USER. // // Add these lines to your LocalSettings.php // /* This is required for Auth_cas operation // require_once('extensions/Auth_cas.php'); // $wgAuth = new Auth_cas(); // // The constructor of Auth_cas registers a hook to do the automatic // login. Storing the Auth_cas object in $wgAuth tells mediawiki to use // that object as the AuthPlugin. This way the login attempts by the hook will // be handled by us. // //Extension credits that show up on Special:Version $wgExtensionCredits['other'][] = array( 'name' => 'Authenticate with CAS Server', 'version' => '1.0', 'author' => array('Ramón Pérez'), 'url' => 'http://www.mediawiki.org/wiki/Extension:AutomaticCAS_USER', 'description' => 'Authenticate for user with a CAS Server.', ); // Setup hooks global $wgHooks; $wgHooks["UserLogoutComplete"][] = "casLogout"; //-------------------------------------------------------------------------- // Configuration Variables //-------------------------------------------------------------------------- $CASAuth = array( "phpCAS" => "$IP/extensions/CASAuth", // Path to phpCAS directory. "Server" => "login.example.es", // Address to CAS server. "Port" => 443, // Port to CAS server. Default: 443. "Url" => "", // Subdir to CAS authentication. "Version" => "2.0", // CAS version, should be either 1.0 or 2.0. "PwdSecret" => "a letters", // A random string that is used when generating the MediaWiki password for this user. YOU SHOULD EDIT THIS TO A VRY RANDOM STRING! YOU SHOULD ALSO KEEP THIS A SECRET! "logoutCAS" => array("server1", "server2"), ); //this is necessary to catch the logout request from CAS Server include_once($CASAuth["phpCAS"]."/CAS.php"); phpCAS::setDebug(); phpCAS::client($CASAuth["Version"], $CASAuth["Server"], $CASAuth["Port"], $CASAuth["Url"]); phpCAS::setNoCasServerValidation(); if ($_REQUEST['service']) : phpCAS::setFixedServiceURL(urlencode($_REQUEST['service'])); endif; phpCAS::handleLogoutRequests(true, $CASAuth["logoutCAS"]); //Check if the user is authenticate phpCAS::CheckAuthentication(); // The Auth_cas class is an AuthPlugin so make sure we have this // included. require_once('AuthPlugin.php'); /** * This hook is registered by the Auth_cas constructor. It will be * called on every page load. It serves the function of automatically logging * in the user. The Auth_cas class is an AuthPlugin and handles the * actual authentication, user creation, etc. * */ function Auth_cas_user_hook() { global $wgUser; global $wgRequest; global $_REQUEST; global $wgAuthRemoteuserDomain; // For a few special pages, don't do anything. $title = $wgRequest->getVal('title'); if ($title == Title::makeName(NS_SPECIAL, 'Userlogout')) { wfDebugLog('CASAuth', 'Logout request'); return; } //If you want more method to login a user, comment this if. //When the requested page is UserLogin, we force to register in CAS Server. if ($title == Title::makeName(NS_SPECIAL, 'Userlogin')){ wfDebugLog('CASAuth', 'Login request'); phpCAS::forceAuthentication(); //Will redirect to CAS server if not logged in wfDebugLog('CASAuth', 'User authenticate in CAS Server'); $returnto = "Portada"; //Name of principal page $target = Title::newFromText($returnto); wfDebugLog('CASAuth', 'redirect to main page'); global $wgOut; $wgOut->redirect($target->getFullUrl()); } // Do nothing if session is valid $user = User::newFromSession(); if ((!$user->isAnon()) && (phpCAS::isSessionAuthenticated())) { wfDebugLog('CASAuth', 'User is not anonymous'); return; // User is already logged in and not anonymous. }else{ wfDebugLog('CASAuth', 'User is anonymous or he is not authenticated in CAS Server'); //if it is not anonymous, we have to logout the user, because logout in another application. Single sign out. if (!$user->isAnon()){ wfDebugLog('CASAuth', 'Logout user, because'); global $wgUser; $wgUser->doLogout(); return; } } // Copied from includes/SpecialUserlogin.php if(!isset($wgCommandLineMode) && !isset($_COOKIE[session_name()])) { wfSetupSession(); } wfDebugLog('CASAuth', 'Check if there is a user authenticate in CAS Server'); if (phpCAS::isSessionAuthenticated()){ //gets the data about user in CAS Server $email = phpCAS::getUser(); //Gets the extra attributes send by CAS Server $extra_attributes = phpCAS::getAttributes(); // Submit a fake login form to authenticate the user. $params = new FauxRequest(array( 'wpName' => $extra_attributes["login"], 'wpPassword' => '', 'wpDomain' => '', 'wpRemember' => '' )); $loginForm = new LoginForm($params); $result = $loginForm->authenticateUserData(); switch ($result) { case LoginForm :: SUCCESS : $wgUser->setOption('rememberpassword', 1); $wgUser->setCookies(); break; case LoginForm :: NO_NAME : $errormessage = 'NoName'; break; case LoginForm :: ILLEGAL : $errormessage = 'Illegal'; break; case LoginForm :: WRONG_PLUGIN_PASS : $errormessage = 'WrongPluginPass'; break; case LoginForm :: NOT_EXISTS : $errormessage = 'NotExists'; break; case LoginForm :: WRONG_PASS : $errormessage = 'WrongPass'; break; case LoginForm :: EMPTY_PASS : $errormessage = 'EmptyPass'; break; default: $errormessage = 'Unknown'; break; } if ($result != LoginForm::SUCCESS) { error_log('Unexpected CAS user authentication failure. Login Error was: '.$errormessage); } return; } } class Auth_cas extends AuthPlugin { function Auth_cas() { // Register our hook function. This hook will be executed on every page // load. Its purpose is to automatically log the user in, if necessary. global $wgExtensionFunctions; if (!isset($wgExtensionFunctions)) { $wgExtensionFunctions = array(); } else if (!is_array($wgExtensionFunctions)) { $wgExtensionFunctions = array( $wgExtensionFunctions ); } array_push($wgExtensionFunctions, 'Auth_cas_user_hook'); return; } /** * Disallow password change. * * @return bool */ function allowPasswordChange() { return false; } /** * This should not be called because we do not allow password change. Always * fail by returning false. * * @param $user User object. * @param $password String: password. * @return bool * @public */ function setPassword($user, $password) { return false; } /** * We don't support this but we have to return true for preferences to save. * * @param $user User object. * @return bool * @public */ function updateExternalDB($user) { return true; } /** * We can't create external accounts so return false. * * @return bool * @public */ function canCreateAccounts() { return false; } /** * We don't support adding users to whatever service provides REMOTE_USER, so * fail by always returning false. * * @param User $user * @param string $password * @return bool * @public */ function addUser($user, $password) { return false; } /** * Pretend all users exist. This is checked by authenticateUserData to * determine if a user exists in our 'db'. By returning true we tell it that * it can create a local wiki user automatically. * * @param $username String: username. * @return bool * @public */ function userExists($username) { return true; } /** * Check whether the given name matches REMOTE_USER. * The name will be normalized to MediaWiki's requirements, so * lower it and the REMOTE_USER before checking. * * @param $username String: username. * @param $password String: user password. * @return bool * @public */ function authenticate($username, $password) { if (!phpCAS::isSessionAuthenticated()){ phpCAS::forceAuthentication(); //Will redirect to CAS server if not logged in return false; } return true; } /** * Check to see if the specific domain is a valid domain. * * @param $domain String: authentication domain. * @return bool * @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 * @public */ function updateUser(&$user) { // We only set this stuff when accounts are created. return true; } /** * Return true because 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. * * @return bool * @public */ function autoCreate() { return true; } /** * Return true to prevent logins that don't authenticate here from being * checked against the local database's password fields. * * @return bool * @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. * * @param $user User object. * @public */ function initUser(&$user) { //get parameters from cas server $email = phpCAS::getUser(); $extra_attributes = phpCAS::getAttributes(); $username = $extra_attributtes["login"]; $user->setRealName($extra_attributes["name"]); $user->setEmail($email); $user->mEmailAuthenticated = wfTimestampNow(); $user->setToken(); //turn on e-mail notifications if (isset($wgAuthRemoteuserNotify) && $wgAuthRemoteuserNotify) { $user->setOption('enotifwatchlistpages', 1); $user->setOption('enotifusertalkpages', 1); $user->setOption('enotifminoredits', 1); $user->setOption('enotifrevealaddr', 1); } $user->saveSettings(); } /** * Modify options in the login template. This shouldn't be very important * because no one should really be bothering with the login page. * * @param $template UserLoginTemplate object. * @public */ function modifyUITemplate(&$template) { //disable the mail new password box $template->set('useemail', false); //disable 'remember me' box $template->set('remember', false); $template->set('create', false); $template->set('domain', false); $template->set('usedomain', false); } /** * Normalize user names to the MediaWiki standard to prevent duplicate * accounts. * * @param $username String: username. * @return string * @public */ function getCanonicalName($username) { // lowercase the username $username = strtolower($username); // uppercase first letter to make MediaWiki happy $username = ucfirst($username); return $username; } } // Function to logout in mediawiki and CAS Server function casLogout() { global $CASAuth; global $wgUser, $wgRequest; // Logout from MediaWiki $wgUser->doLogout(); // Get returnto value $returnto = $wgRequest->getVal("returnto"); if ($returnto) { $target = Title::newFromText($returnto); if ($target) { $redirecturl = $target->getFullUrl(); } } if (isset($redirecturl)) { phpCAS::logoutWithRedirectServiceAndUrl($redirecturl, $redirecturl); } else { phpCAS::logout(); } return true; // We won't get here } ?>
