eesyphp/src/Auth/Cas.php

153 lines
4.1 KiB
PHP

<?php
namespace EesyPHP\Auth;
use EesyPHP\App;
use EesyPHP\Auth;
use EesyPHP\Log;
use EesyPHP\Url;
use phpCAS;
class Cas extends Method {
/**
* Fake authenticated user login
* @var string|null
*/
private static $fake_authenticated_user = null;
/**
* Initialize
* @return boolean
*/
public static function init() {
// In phpstan context, do not initialize
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) // @phpstan-ignore-line
return true;
// Set config default values
App :: set_default(
'auth.cas',
array(
'host' => null,
'port' => 443,
'context' => '/idp/cas',
'version' => '2.0',
'logout' => true,
'fake_authenticated_user' => null,
'debug_log_file' => null,
'ca_cert_certificate_path' => null,
)
);
self :: $fake_authenticated_user = App :: get(
'auth.cas.fake_authenticated_user', null, 'string');
if (self :: $fake_authenticated_user) return true;
if (App::get('auth.cas.debug_log_file'))
phpCAS::setDebug(App::get('auth.cas.debug_log_file'));
if (!App::get('auth.cas.host')) {
Log :: error('CAS host not configured. Check your configuration!');
return false;
}
$cas_version = App :: get('auth.cas.version', null, 'string');
$supported_cas_versions = phpCAS::getSupportedProtocols();
if (!array_key_exists($cas_version, $supported_cas_versions)) {
Log :: error(
'Unsupported CAS version (%s). Check your configuration!',
$cas_version
);
return false;
}
// Init phpCAS client
phpCAS::client(
$cas_version,
App :: get('auth.cas.host'),
App :: get('auth.cas.port', null, 'int'),
App :: get('auth.cas.context', null, 'string'),
Url :: get_absolute_url("/")
);
if (App :: get('auth.cas.ca_cert_certificate_path'))
phpCAS::setCasServerCACert(App :: get('auth.cas.ca_cert_certificate_path'));
else
phpCAS::setNoCasServerValidation();
Url :: add_url_handler(
'#^login/cas_callback$#', array('EesyPHP\\Auth\\Cas', 'handle_cas_callback'), null, false);
return true;
}
/**
* Compute CAS callback URL
* @return string
*/
private static function get_cas_callback_url() {
return Url :: get_absolute_url(
'login/cas_callback?next='.(
isset($_REQUEST['next'])?
$_REQUEST['next']:
urlencode(Url :: get_current_url())
)
);
}
/**
* Log user
* @param bool $force Force user authentication
* @return \EesyPHP\Auth\User|null
*/
public static function login($force=false) {
if (self :: $fake_authenticated_user) {
$user = Auth :: get_user(self :: $fake_authenticated_user);
}
else {
if (!phpCAS :: isAuthenticated() && $force) {
$_SESSION['cas_callback_url'] = self :: get_cas_callback_url();
phpCAS :: setFixedServiceURL($_SESSION['cas_callback_url']);
phpCAS :: forceAuthentication();
}
$user = (
phpCAS :: isAuthenticated()?
Auth :: get_user(phpCAS :: getUser()):
null
);
}
if ($force && !$user)
Log :: fatal('Fail to authenticate you');
return $user;
}
/**
* Logout
* @return void
*/
public static function logout() {
if (App :: get('auth.cas.logout', null, 'bool') && !self :: $fake_authenticated_user) {
if (App :: get('auth.cas.logout_url'))
Url :: redirect(App :: get('auth.cas.logout_url'));
phpCAS::logout();
}
else {
session_unset();
session_destroy();
}
}
/**
* The CAS callback view
* @param \EesyPHP\UrlRequest $request
* @return never
*/
public static function handle_cas_callback($request) {
if (isset($_SESSION['cas_callback_url'])) {
phpCAS :: setFixedServiceURL($_SESSION['cas_callback_url']);
unset($_SESSION['cas_callback_url']);
}
$user = Auth :: login(false, 'Cas');
if ($user)
Url :: redirect(isset($_REQUEST['next'])?urldecode($_REQUEST['next']):null);
Log :: fatal('No CAS ticket or fail to authenticate you');
}
}