This module allows authentication against a CAS server. It is designed as an extension of the LDAP backend so CAS can be used for authentication and LDAP for ACL management.
It requires a small modification of two core dokuwiki files.
I created a similar auth backend in June. Mine uses plain authentication as its source and also ggauth so that I can manage groups locally while only doing the authentication through CAS. The code is pretty similar to what is below.
Here is a link: http://wiki.cornempire.net/doku.php?id=dokuwikicas:start
Note for Cornempire: If you need Single Sign Out you must put this in your login ACT
if ($ACT == 'login') { phpCAS::setFixedServiceURL('http://{YOUR CAS LOGIN SERVICE}?service={YOUR WIKI URL}/doku.php?' . $_SERVER["QUERY_STRING"]); phpCAS::handleLogoutRequests(true, array("server1.domain.edu", "server2.domain.edu")); phpCAS::forceAuthentication(); }
Download the following zip file and extract it to the inc/auth directory.
It contains the phpCas library files and the cas.class.php file
I cannot upload the file, so here is the content of the cas.class.php file (inspired from this site). Place this file in the inc/auth directory :
<?php /** * Inspired from * http://www.esup-portail.org/display/PROJDOCUWIKICAS/CASification+de+Docuwiki;jsessionid=58187C0F5A8834D07E6D7F1EB30744C2 */ require_once(DOKU_INC.'inc/auth/ldap.class.php'); include_once('CAS/CAS.php'); global $conf; class auth_cas extends auth_ldap { public $cnfcas = null; function __construct() { global $conf; parent::__construct(); $this->cnfcas = $conf['auth']['cas']; $this->cando['external'] = true; $this->cando['login'] = true; $this->cando['logoff'] = true; // curl extension is needed if(!function_exists('curl_init')) { if ($this->cnf['debug']) msg("CAS err: CURL extension not found.",-1,__LINE__,__FILE__); $this->success = false; return; } phpCAS::client(CAS_VERSION_2_0, $this->cnfcas['server'], (int) $this->cnfcas['port'], $this->cnfcas['rootcas']); // automatically log the user when there is a cas session opened if($this->cnfcas['autologin']) { phpCAS::setCacheTimesForAuthRecheck(1); } else { phpCAS::setCacheTimesForAuthRecheck(-1); } if($this->cnfcas['cert']) { phpCAS::setCasServerCert($this->cnfcas['cert']); } elseif($this->cnfcas['cacert']) { phpCAS::setCasServerCACert($this->cnfcas['cacert']); } else { phpCAS::setNoCasServerValidation(); } if($this->cnfcas['handlelogoutrequest']) { phpCAS::handleLogoutRequests(); } else { phpCAS::handleLogoutRequests(false); } } public function trustExternal($user,$pass,$sticky=false) { global $USERINFO; global $conf; $sticky ? $sticky = true : $sticky = false; //sanity check $session = $_SESSION[$conf['title']]['auth']; if(phpCAS::checkAuthentication()) { $user = phpCAS::getUser(); if(isset($session)) { $_SERVER['REMOTE_USER'] = $user; $USERINFO = $session['info']; $_SESSION[$conf['title']]['auth']['user'] = $user; $_SESSION[$conf['title']]['auth']['pass'] = $session['pass']; $_SESSION[$conf['title']]['auth']['info'] = $USERINFO; $_SESSION[$conf['title']]['auth']['buid'] = $session['buid']; } else { $USERINFO = $this->getUserData($user); $_SERVER['REMOTE_USER'] = $user; $_SESSION[$conf['title']]['auth']['user'] = $user; $_SESSION[$conf['title']]['auth']['pass'] = $pass; $_SESSION[$conf['title']]['auth']['info'] = $USERINFO; $_SESSION[$conf['title']]['auth']['buid'] = auth_browseruid(); } return true; } return false; } public function logIn() { global $QUERY; phpCAS::setFixedServiceURL(DOKU_URL . 'doku.php?id=' . $QUERY); phpCAS::forceAuthentication(); } public function logOff() { global $QUERY; if($this->cnfcas['caslogout']) { // dokuwiki + cas logout @session_start(); session_destroy(); phpCAS::logoutWithRedirectService(DOKU_URL . 'doku.php?id=' . $QUERY); } else { // dokuwiki logout only @session_start(); session_destroy(); } } } //Setup VIM: ex: et ts=4 enc=utf-8 :
The phpCas library can be downloaded here. Place the CAS directory and its content in the inc/auth directory.
The phpCas library needs
CURL libs must be present on your system, and they must have been compiled with SSL support. More informations on phpCas requirements
Edit the file inc/auth/basic.class.php and replace
'logoff' => false, // has the module some special logoff method?
by
'logoff' => false, // has the module some special logoff method? 'login' => false, // has the module some special login method?
Edit the file inc/actions.php and replace :
function act_auth($act){ global $ID; global $INFO;
by :
function act_auth($act){ global $ID; global $INFO; global $auth; if($auth->cando['login'] && $act == 'login') { $auth->logIn(); }
This is an example configuration to set in your conf/local.php to authenticate against your CAS server.
$conf['authtype'] = 'cas'; /* CAS specific configuration */ $conf['auth']['cas']['server'] = 'cas.server.tld'; $conf['auth']['cas']['port'] = 443; // CAS server root parameter $conf['auth']['cas']['rootcas'] = 'cas'; // automatically log the user when there is already a CAS session opened $conf['auth']['cas']['autologin'] = 1; // log out from the CAS server when loggin out from dokuwiki $conf['auth']['cas']['caslogout'] = 1; // log out from dokuwiki when loggin out from the CAS server (should work with CASv3, experimental) $conf['auth']['cas']['handlelogoutrequest'] = 0; /* LDAP usual configuration */ $conf['auth']['ldap']['server'] = 'ldap://server.tld:389'; $conf['auth']['ldap']['usertree'] = 'ou=People, dc=server, dc=tld'; $conf['auth']['ldap']['grouptree'] = 'ou=Group, dc=server, dc=tld'; $conf['auth']['ldap']['userfilter'] = '(&(uid=%{user})(objectClass=posixAccount))'; $conf['auth']['ldap']['groupfilter'] = '(&(objectClass=posixGroup)(|(gidNumber=%{gid})(memberUID=%{user})))';
If you don't add this in basic auth, then
if($auth->cando['login'] && $act == 'login') { $auth->logIn(); }
can look for an undefined index.
public function trustExternal($user,$pass,$sticky=false) {
global $USERINFO;
global $conf;
$sticky ? $sticky = true : $sticky = false; //sanity check
$session = $_SESSION[$conf['title']]['auth'];
if(phpCAS::checkAuthentication()) {
$user = phpCAS::getUser();
if(isset($session)) {
$_SERVER['REMOTE_USER'] = $user;
$USERINFO = $session['info'];
$_SESSION[$conf['title']]['auth']['user'] = $user;
$_SESSION[$conf['title']]['auth']['pass'] = $session['pass'];
$_SESSION[$conf['title']]['auth']['info'] = $USERINFO;
$_SESSION[$conf['title']]['auth']['buid'] = $session['buid'];
}
else {
$USERINFO = $this->getUserData($user);
$_SERVER['REMOTE_USER'] = $user;
$_SESSION[$conf['title']]['auth']['user'] = $user;
$_SESSION[$conf['title']]['auth']['pass'] = $pass;
$_SESSION[$conf['title']]['auth']['info'] = $USERINFO;
$_SESSION[$conf['title']]['auth']['buid'] = auth_browseruid();
}
return true;
}
else {
phpCAS::forceAuthentication();
}
return false;
}
I just added the part :
else {
phpCAS::forceAuthentication();
}