Skip to content
Snippets Groups Projects
Select Git revision
  • develop
  • master default protected
  • git-fixes
  • 4.1_templates-symlink
  • 4.0_templates
5 results

start.php

Blame
  • start.php 9.08 KiB
    <?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 = NULL) {
            // 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 = NULL) {
            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 = NULL) {
            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 = NULL) {
            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 = 'https://directory.unl.edu/';
        
        public static $cert_path = '/etc/pki/tls/cert.pem';
        
        function __construct() {
            if (!\phpCAS::isInitialized()) {
                \phpCAS::client(CAS_VERSION_2_0, 'shib.unl.edu', 443, 'idp/profile/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()
        {
            // Setting a custom path is done by passing an options array to the constructor.
            $options = array('path' => __DIR__ .'/../../tmp/elgg_session_map');
            
            $driver = new Stash\Driver\FileSystem($options);
    
            $pool = new Stash\Pool($driver);
            
            return $pool;
        }
        
        public function singleLogOut()
        {
            \phpCAS::handleLogoutRequests(false);
        }
        
        public function autoLogin()
        {
            if ('pg' == elgg_get_context() && false !== strpos($_SERVER['REQUEST_URI'], '/pg/icon/')) {
                //Don't auto-login on profile icon view
                return;
            }
            
            if (false !== strpos($_SERVER['REQUEST_URI'], '/mod/profile/icondirect.php')) {
                //prevent auto-login for the icondirect.php endpoint too
                return;
            }
    
            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();
        }
    }