<?php /** * Elgg UNL CAS authentication * * @package cas_auth_unl * @license BSD http://www1.unl.edu/wdn/wiki/Software_License * @author University of Nebraska-Lincoln * @copyright 2010 Regents of the University of Nebraska * @link http://www.unl.edu/ */ global $CONFIG; require_once __DIR__ . '/vendor/autoload.php'; function cas_auth_unl_init() { global $CONFIG; $auth = new UnlCAS(); $auth->autoLogin(); $auth->singleLogOut(); // Set up login page, this creates the url /login to be used as our login page elgg_register_page_handler('login', 'cas_auth_unl_login_page_handler'); elgg_register_page_handler('logout', 'cas_auth_unl_logout_page_handler'); elgg_register_page_handler('register', 'cas_auth_unl_registration_page_handler'); /* set up getemail page */ elgg_register_page_handler('getemail', 'cas_auth_unl_getemail_page_handler'); elgg_register_action('getemail', $CONFIG->pluginspath . 'cas_auth_unl/actions/getemail.php', 'public'); elgg_register_action('logout', $CONFIG->pluginspath . 'cas_auth_unl/actions/logout.php', 'public'); } // Fire up the plugin initialization using the elgg handler elgg_register_event_handler('init','system','cas_auth_unl_init'); function cas_auth_unl_login_page_handler($page) { // If we're not logged in, display the login page if (!elgg_is_logged_in()) { $auth = new UnlCAS(); $auth->forceLogin(); } // Otherwise, forward to the index page forward(); } function cas_auth_unl_logout_page_handler($page) { if (elgg_is_logged_in()) { // If we're not logged in, display the login page $auth = new UnlCAS(); $auth->forceLogout(); } // Otherwise, forward to the index page forward(); } function cas_auth_unl_registration_page_handler($page) { if (elgg_is_logged_in()) { // Otherwise, forward to the index page forward(); } if (!isset($_SESSION['cas_auth_unl']['register']['uid'])) { //They are not already in the registration process forward(); } if (!isset($_POST['email'])) { forward(); } // If we're not logged in, display the login page $auth = new UnlCAS(); $unl_uid = $_SESSION['cas_auth_unl']['register']['uid']; $auth->register($unl_uid, $_POST['email']); $auth->login($unl_uid); forward(); } function cas_auth_unl_getemail_page_handler($page) { if (!elgg_get_logged_in_user_entity()) { echo elgg_view_page(elgg_echo('Your Email'), elgg_view("account/forms/getemail")); } else { forward(); } } class UnlCAS { var $client; var $casInitialized = false; const DIRECTORY_URL = 'http://directory.unl.edu/'; public static $cert_path = '/etc/pki/tls/cert.pem'; function __construct() { if (!\phpCAS::isInitialized()) { \phpCAS::client(CAS_VERSION_2_0, 'login.unl.edu', 443, 'cas'); \phpCAS::setCasServerCACert(self::$cert_path); \phpCAS::setPostAuthenticateCallback(function($logoutTicket) { $auth = new UnlCAS(); $auth->loginOrRegister(\phpCAS::getUser()); $session = elgg_get_session(); $pool = $auth->getSessionMapPool(); $item = $pool->getItem($logoutTicket); $item->set(array( 'session_id' => $session->getId(), 'date_created' => time() )); }); \phpCAS::setSingleSignoutCallback(function ($logoutTicket) { $auth = new UnlCAS(); $pool = $auth->getSessionMapPool(); $item = $pool->getItem($logoutTicket); if ($item->isMiss()) { return null; } $data = $item->get(); $handler = new Elgg\Http\DatabaseSessionHandler(_elgg_services()->db); if (!$handler->destroy($data['session_id'])) { throw new \Exception('unable to destroy session on single sign out'); } //Remove the cached item $item->clear(); }); } } public function getSessionMapPool() { $driver = new Stash\Driver\FileSystem(); // Setting a custom path is done by passing an options array to the constructor. $options = array('path' => __DIR__ .'/../../tmp/elgg_session_map'); $driver->setOptions($options); $pool = new Stash\Pool($driver); return $pool; } public function singleLogOut() { \phpCAS::handleLogoutRequests(false); } public function autoLogin() { if (!array_key_exists('unl_sso', $_COOKIE)) { //No unl_sso cookie was found, no need to auto-login. return; } if (elgg_get_logged_in_user_entity()) { //We are already logged in, no need to auto-login return; } //Everything looks good. Log in! $result = \phpCAS::checkAuthentication(); if ($result) { //Make sure we are still authenticated with CAS //setPostAuthenticateCallback() will actually do the work \phpCAS::renewAuthentication(); } } protected function loginOrRegister($unl_uid) { $elgg_uid = $this->toElggUID($unl_uid); $user = get_user_by_username($elgg_uid); if (!$user) { $this->register($unl_uid); $this->login($unl_uid); } else { $this->login($unl_uid); } } public function login($unl_uid) { $user = get_user_by_username($this->toElggUID($unl_uid)); //Log the user into elgg login($user); } public function register($unl_uid, $student_email = false) { $elgg_uid = $this->toElggUID($unl_uid); $directory_info = $this->getDirectoryInfo($unl_uid); $name = 'unknown'; $email = false; if ($student_email) { $email = $student_email; } if (isset($directory_info['name'])) { $name = $directory_info['name']; } if (isset($directory_info['email'])) { //Override the student email with the one from the directory $email = $directory_info['email']; } if (false === $email) { $_SESSION['cas_auth_unl']['register']['uid'] = $unl_uid; forward('getemail'); } $password = generate_random_cleartext_password(); try { $user_guid = register_user($elgg_uid, $password, $name, $email, false); } catch (RegistrationException $e) { //Looks like we had an invalid email address... ask for it again. register_error(elgg_echo($e->getMessage())); forward('getemail'); } if (!$user_guid) { register_error(elgg_echo("registerbad")); } //Make sure that this gets unset unset($_SESSION['cas_auth_unl']); return true; } protected function getDirectoryInfo($uid) { $info = array(); if (!$json = @file_get_contents(self::DIRECTORY_URL . '?uid=' . $uid . '&format=json')) { return $info; } if (!$json = json_decode($json, true)) { return $info; } $map = array( 'givenName' => 'first_name', 'sn' => 'last_name', 'mail' => 'email' ); foreach ($map as $from => $to) { if (isset($json[$from][0])) { $info[$to] = $json[$from][0]; } } $info['name'] = $info['first_name'] . ' ' . $info['last_name']; return $info; } protected function toElggUID($unl_uid) { $unl_uid = str_replace('-','_',$unl_uid); return 'unl_' . $unl_uid; } public function forceLogin() { //Due to the weirdness of phpCAS, it might think we are still logged in (when we are not) $_SESSION['phpCAS'] = array(); \phpCAS::forceAuthentication(); } public function forceLogout() { //log out of elgg logout(); //log out of CAS \phpCAS::logout(); } }