test-cas-client-sp/index.php
2022-07-09 20:16:15 +02:00

416 lines
12 KiB
PHP

<?php
/*
************************************
* Configuration *
************************************
*/
// PhpCAS library path
$phpCAS_path = "CAS.php";
// All valid CAS servers
$cas_servers = array(
// CAS server hostname
$_SERVER['SERVER_NAME'] => array(
// Context of the CAS Server
'context' => '/idp/cas',
// CAS server port
'port' => 8443,
// If you running this application in HTTP only, uncomment following parameter
//'insecure' => true,
// Disable CAS server Validation
'ssl_validation' => false,
// If ssl_validation is enable you must define
'ssl_cacert_path' => '/etc/ssl/certs/ca-certificates.crt',
'ssl_cn_validation' => true,
// Extra CURL options (for phpCAS client)
'extra_curl_options' => array(
// Uncomment it in case of 'dh key too small' error
// 'CURLOPT_SSL_CIPHER_LIST' => 'DEFAULT@SECLEVEL=1',
),
),
$_SERVER['SERVER_NAME'].'2' => array(
// Context of the CAS Server
'context' => '/idp/cas',
// CAS server port
'port' => 8443,
// If you running this application in HTTP only, uncomment following parameter
//'insecure' => true,
// Disable CAS server Validation
'ssl_validation' => false,
// If ssl_validation is enable you must define
'ssl_cacert_path' => '/etc/ssl/certs/ca-certificates.crt',
'ssl_cn_validation' => true,
// Extra CURL options (for phpCAS client)
'extra_curl_options' => array(
// Uncomment it in case of 'dh key too small' error
// 'CURLOPT_SSL_CIPHER_LIST' => 'DEFAULT@SECLEVEL=1',
),
),
);
// FQDN of CAS server
$default_cas_server = key($cas_servers);
// PhpCAS debug logs
// Log directory path
$phpCAS_logdir = 'logs';
// Log filename format
// Compose with :
// - {cas_server} : the CAS server
// - {remote_addr} : connected user remote IP address
// - {session_id} : connected user session_id
$phpCAS_logfile_format = '{session_id}-{cas_server}.log';
// Local app URL (auto-detect on first acces if null)
$service_url = null;
/*
************************************
* Main *
************************************
*/
$warnings = array();
session_start();
require $phpCAS_path;
CAS_GracefullTerminationException::throwInsteadOfExiting();
// Initialize session variables
if (isset($_SESSION['cas_server']) && array_key_exists($_SESSION['cas_server'], $cas_servers)) {
$cas_host = $_SESSION['cas_server'];
}
else {
$_SESSION['cas_server'] = $cas_host = $default_cas_server;
}
if (!isset($_SESSION['user'])) $_SESSION['user'] = null;
if (!isset($_SESSION['attributes'])) $_SESSION['attributes'] = null;
// Generate phpCAS debug log file path
$phpCAS_logfile = "$phpCAS_logdir/$phpCAS_logfile_format";
$phpCAS_logfile = str_replace('{cas_server}', $cas_host, $phpCAS_logfile);
$phpCAS_logfile = str_replace('{remote_addr}', $_SERVER['REMOTE_ADDR'], $phpCAS_logfile);
$phpCAS_logfile = str_replace('{session_id}', session_id(), $phpCAS_logfile);
$phpCAS_config = array();
function init_phpCAS() {
global $phpCAS_logfile, $phpCAS_config, $warnings, $cas_host, $cas_servers, $service_url;
// Make sure service URL is defined (otherwise, load it from session or auto-detect)
if (is_null($service_url)) {
if (isset($_SESSION['service_url'])) {
$service_url = $_SESSION['service_url'];
}
else {
$https = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
$request_uri = $_SERVER['REQUEST_URI'];
$request_uri = preg_replace('/\?.*$/', '', $request_uri);
$service_url = "http".($https?"s":"")."://".$_SERVER['SERVER_NAME'];
if (($_SERVER['SERVER_PORT'] != 443 && $https) || ($_SERVER['SERVER_PORT'] != 80 && !$https))
$service_url .= ":".$_SERVER['SERVER_PORT'];
$service_url .= $request_uri;
$_SESSION['service_url'] = $service_url;
}
}
// Compute phpCAS configuration
$phpCAS_config = array(
'CAS Hostname' => $cas_host,
'CAS server port' => $cas_servers[$cas_host]['port'],
'CAS server context' => $cas_servers[$cas_host]['context'],
'Service URL' => $service_url,
);
// Set phpCAS log file
if (is_writable($phpCAS_logfile) || (!is_file($phpCAS_logfile) && is_writable(dirname($phpCAS_logfile)))) {
$phpCAS_config['Debug file'] = $phpCAS_logfile;
phpCAS::setDebug($phpCAS_logfile);
}
try {
phpCAS::client(
CAS_VERSION_2_0,
$cas_host,
$cas_servers[$cas_host]['port'],
$cas_servers[$cas_host]['context']
);
phpCAS::setNoClearTicketsFromUrl();
phpCAS::setFixedServiceURL($service_url);
// Set extra CURL options
if (isset($cas_servers[$cas_host]['extra_curl_options']) && is_array($cas_servers[$cas_host]['extra_curl_options'])) {
foreach($cas_servers[$cas_host]['extra_curl_options'] as $opt => $value) {
if (is_string($opt) && substr($opt, 0, 7) == 'CURLOPT' && defined($opt))
$opt = constant($opt);
phpCAS::setExtraCurlOption($opt, $value);
}
}
if ($cas_servers[$cas_host]['insecure']) {
$phpCAS_config['Insecure'] = 'Yes';
$phpCAS_config['Base URL'] = 'http://'.$cas_host.($cas_servers[$cas_host]['port']?':'.$cas_servers[$cas_host]['port']:'').$cas_servers[$cas_host]['context'];
// Remove trailing slash if present
if (substr($phpCAS_config['Base URL'], -1)=='/')
$phpCAS_config['Base URL'] = substr($phpCAS_config['Base URL'], 0, -1);
$phpCAS_config['Login URL'] = $phpCAS_config['Base URL']."/login?service=".urlencode($service_url);
$phpCAS_config['Logout URL'] = $phpCAS_config['Base URL']."/logout";
$phpCAS_config['Service validate URL'] = $phpCAS_config['Base URL']."/serviceValidate";
phpCAS::setServerLoginURL($phpCAS_config['Login URL']);
phpCAS::setServerLogoutURL($phpCAS_config['Logout URL']);
phpCAS::setServerServiceValidateURL($phpCAS_config['Service validate URL']);
// Be sure SSL validation is disabled
$cas_servers[$cas_host]['ssl_validation'] = false;
}
else
$phpCAS_config['Insecure'] = 'No';
if ($cas_servers[$cas_host]['ssl_validation'] === true) {
if (is_readable($cas_servers[$cas_host]['ssl_cacert_path'])) {
$phpCAS_config['SSL Validation'] = 'Enabled';
$phpCAS_config['SSL CA Cert Validation File'] = $cas_servers[$cas_host]['ssl_cacert_path'];
$phpCAS_config['SSL CN Validation'] = (
$cas_servers[$cas_host]['ssl_cn_validation']?
'Enabled':'Disabled'
);
phpCAS::setCasServerCACert(
$cas_servers[$cas_host]['ssl_cacert_path'],
$cas_servers[$cas_host]['ssl_cn_validation']
);
}
else {
$warnings[] = 'SSL validation enable for this server but CA Cert file configured does not exists or is not readable';
$phpCAS_config['SSL Validation'] = 'Disabled';
phpCAS::setNoCasServerValidation();
}
}
else {
$phpCAS_config['SSL Validation'] = 'Disabled';
phpCAS::setNoCasServerValidation();
}
phpCAS::setCacheTimesForAuthRecheck(0);
}
catch (CAS_GracefullTerminationException $e) {
$warnings[] = 'PhpCAS return exception';
return false;
}
return true;
}
function local_logout() {
unset($_SESSION['session_url']);
unset($_SESSION['phpCAS']);
unset($_SESSION['user']);
unset($_SESSION['attributes']);
return !isset($_SESSION['phpCAS']);
}
function json_output($success=true, $data=null, $return_code=200, $exit=true) {
global $warnings, $phpCAS_config, $phpCAS_logfile, $cas_servers;
// Retreive phpCAS logs
$logs = false;
if (is_writable($phpCAS_logfile)) {
$lines = file($phpCAS_logfile);
if (is_array($lines)) {
$logs = implode('',$lines);
}
else {
$warnings[] = "Error reading PhpCAS debug log file ($phpCAS_logfile).";
}
}
else {
$warnings[] = "PhpCAS debug log file does not exists or is not writable ($phpCAS_logfile).";
}
// Compute return data
$return = array(
'success' => $success,
'data' => $data,
'logs' => $logs,
'warnings' => $warnings,
'config' => $phpCAS_config,
'cas_servers' => $cas_servers,
'cas_server' => $_SESSION['cas_server'],
'user' => $_SESSION['user'],
'attributes' => $_SESSION['attributes'],
);
// Handle JSON output
http_response_code($return_code);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($return);
if ($exit) exit();
}
// Handle API call
if (isset($_REQUEST['do'])) {
switch($_REQUEST['do']) {
case 'status':
json_output(init_phpCAS());
break;
case 'change_server':
if (!isset($_REQUEST['server'])) {
$warnings[] = "Invalid parameters: selected CAS server is missing.";
json_output(false);
}
if (!isset($cas_servers[$_REQUEST['server']])) {
$warnings[] = "Invalid CAS server choiced";
json_output(false);
}
if ($_SESSION['cas_server'] != $_REQUEST['server']) {
local_logout();
}
$cas_host = $_SESSION['cas_server'] = $_REQUEST['server'];
json_output(init_phpCAS());
break;
case 'login':
if (!init_phpCAS()) json_output(false);
if (phpCAS::isAuthenticated()) {
$warnings[] = 'Already authenticated. Please logout (at least local logout) before.';
json_output(false);
}
json_output(true, array('login_url' => phpCAS::getServerLoginURL()));
break;
case 'validate_ticket':
if (!init_phpCAS()) json_output(false);
if (phpCAS::isAuthenticated()) {
$_SESSION['user'] = phpCAS::getUser();
$_SESSION['attributes'] = phpCAS::getAttributes();
json_output(true);
}
else {
$warnings[] = 'Fail to validate ticket, please check logs.';
json_output(false);
}
break;
case 'logout':
if (!init_phpCAS()) json_output(false);
if (!phpCAS::isAuthenticated()) {
$warnings[] = 'Not currently authenticated.';
json_output(false);
}
if (!local_logout()) {
$warnings[] = 'Fail to purge local session.';
json_output(false);
}
$logout_url = phpCAS::getServerLogoutURL().'?<se></se>rvice='.$service_url;
json_output(true, array('logout_url' => $logout_url));
break;
case 'locallogout':
unset($_SESSION['session_url']);
unset($_SESSION['phpCAS']);
unset($_SESSION['user']);
unset($_SESSION['attributes']);
json_output();
break;
case 'truncatelog':
$success = false;
if (is_file($phpCAS_logfile)) {
if (!is_writable(dirname($phpCAS_logfile))) {
$warnings[] = 'Logs directory is not writable ('.dirname($phpCAS_logfile).').';
json_output(false);
}
$fh = fopen($phpCAS_logfile, 'w');
fclose($fh);
}
json_output(true);
break;
default:
$warnings[] = 'Invalid request';
json_output(false);
}
}
?>
<html>
<head>
<title>Test CAS</title>
<script src="jquery-3.6.0.min.js"></script>
<script src="app.js"></script>
<style>
h2 {
border-bottom: 1px solid;
}
strong {
font-size: 0.9em;
}
em {
font-size: 0.8em;
}
#warnings {
color: #fff;
background-color: #C56E6E;
}
pre {
margin-left: 1em;
padding: 1em;
border-left: 1px solid;
background-color: #eee;
font-size: 0.9em;
}
/* Defaulty hide UI components (expect menu) */
#cas_server_selection, #cas_config, #user_info, #warnings, #cas_logs {
display: none;
}
</style>
</style>
<body>
<h1>Test CAS Application</h1>
<div id='cas_server_selection'>
<h2>CAS server selection</h2>
<form action='index.php' method='POST'>
<label for='server'>CAS server</label> :
<select name='server' id='select_server'></select>
</form>
</div>
<div id='cas_config'>
<h2>PhpCAS configuration</h2>
<ul></ul>
</div>
<h2>Menu</h2>
<ul>
<li><button id='login_btn'>Login</button></li>
<li><button id='caslogout_btn'>Logout on CAS server</button></li>
<li><button id='locallogout_btn'>Logout on local application</button></li>
<li><button id='truncatelog_btn'>Truncate Debug log file content</button></li>
</ul>
<div id='user_info'></div>
<div id='warnings'></div>
<div id='cas_logs'>
<h2>PhpCAS Debug logs</h2>
<pre></pre>
</div
</body>
</html>