/auth/cas/CAS/CAS/Client.php
PHP | 4004 lines | 2354 code | 286 blank | 1364 comment | 321 complexity | 5cc3f5381cafb2017c80b3d587410957 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * Licensed to Jasig under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * Jasig licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * PHP Version 5
- *
- * @file CAS/Client.php
- * @category Authentication
- * @package PhpCAS
- * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
- * @author Olivier Berger <olivier.berger@it-sudparis.eu>
- * @author Brett Bieber <brett.bieber@gmail.com>
- * @author Joachim Fritschi <jfritschi@freenet.de>
- * @author Adam Franco <afranco@middlebury.edu>
- * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
- * @link https://wiki.jasig.org/display/CASC/phpCAS
- */
- /**
- * The CAS_Client class is a client interface that provides CAS authentication
- * to PHP applications.
- *
- * @class CAS_Client
- * @category Authentication
- * @package PhpCAS
- * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
- * @author Olivier Berger <olivier.berger@it-sudparis.eu>
- * @author Brett Bieber <brett.bieber@gmail.com>
- * @author Joachim Fritschi <jfritschi@freenet.de>
- * @author Adam Franco <afranco@middlebury.edu>
- * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
- * @link https://wiki.jasig.org/display/CASC/phpCAS
- *
- */
- class CAS_Client
- {
- // ########################################################################
- // HTML OUTPUT
- // ########################################################################
- /**
- * @addtogroup internalOutput
- * @{
- */
- /**
- * This method filters a string by replacing special tokens by appropriate values
- * and prints it. The corresponding tokens are taken into account:
- * - __CAS_VERSION__
- * - __PHPCAS_VERSION__
- * - __SERVER_BASE_URL__
- *
- * Used by CAS_Client::PrintHTMLHeader() and CAS_Client::printHTMLFooter().
- *
- * @param string $str the string to filter and output
- *
- * @return void
- */
- private function _htmlFilterOutput($str)
- {
- $str = str_replace('__CAS_VERSION__', $this->getServerVersion(), $str);
- $str = str_replace('__PHPCAS_VERSION__', phpCAS::getVersion(), $str);
- $str = str_replace('__SERVER_BASE_URL__', $this->_getServerBaseURL(), $str);
- echo $str;
- }
- /**
- * A string used to print the header of HTML pages. Written by
- * CAS_Client::setHTMLHeader(), read by CAS_Client::printHTMLHeader().
- *
- * @hideinitializer
- * @see CAS_Client::setHTMLHeader, CAS_Client::printHTMLHeader()
- */
- private $_output_header = '';
- /**
- * This method prints the header of the HTML output (after filtering). If
- * CAS_Client::setHTMLHeader() was not used, a default header is output.
- *
- * @param string $title the title of the page
- *
- * @return void
- * @see _htmlFilterOutput()
- */
- public function printHTMLHeader($title)
- {
- $this->_htmlFilterOutput(
- str_replace(
- '__TITLE__', $title,
- (empty($this->_output_header)
- ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
- : $this->_output_header)
- )
- );
- }
- /**
- * A string used to print the footer of HTML pages. Written by
- * CAS_Client::setHTMLFooter(), read by printHTMLFooter().
- *
- * @hideinitializer
- * @see CAS_Client::setHTMLFooter, CAS_Client::printHTMLFooter()
- */
- private $_output_footer = '';
- /**
- * This method prints the footer of the HTML output (after filtering). If
- * CAS_Client::setHTMLFooter() was not used, a default footer is output.
- *
- * @return void
- * @see _htmlFilterOutput()
- */
- public function printHTMLFooter()
- {
- $lang = $this->getLangObj();
- $this->_htmlFilterOutput(
- empty($this->_output_footer)?
- (phpCAS::getVerbose())?
- '<hr><address>phpCAS __PHPCAS_VERSION__ '
- .$lang->getUsingServer()
- .' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>'
- :'</body></html>'
- :$this->_output_footer
- );
- }
- /**
- * This method set the HTML header used for all outputs.
- *
- * @param string $header the HTML header.
- *
- * @return void
- */
- public function setHTMLHeader($header)
- {
- // Argument Validation
- if (gettype($header) != 'string')
- throw new CAS_TypeMismatchException($header, '$header', 'string');
- $this->_output_header = $header;
- }
- /**
- * This method set the HTML footer used for all outputs.
- *
- * @param string $footer the HTML footer.
- *
- * @return void
- */
- public function setHTMLFooter($footer)
- {
- // Argument Validation
- if (gettype($footer) != 'string')
- throw new CAS_TypeMismatchException($footer, '$footer', 'string');
- $this->_output_footer = $footer;
- }
- /** @} */
- // ########################################################################
- // INTERNATIONALIZATION
- // ########################################################################
- /**
- * @addtogroup internalLang
- * @{
- */
- /**
- * A string corresponding to the language used by phpCAS. Written by
- * CAS_Client::setLang(), read by CAS_Client::getLang().
- * @note debugging information is always in english (debug purposes only).
- */
- private $_lang = PHPCAS_LANG_DEFAULT;
- /**
- * This method is used to set the language used by phpCAS.
- *
- * @param string $lang representing the language.
- *
- * @return void
- */
- public function setLang($lang)
- {
- // Argument Validation
- if (gettype($lang) != 'string')
- throw new CAS_TypeMismatchException($lang, '$lang', 'string');
- phpCAS::traceBegin();
- $obj = new $lang();
- if (!($obj instanceof CAS_Languages_LanguageInterface)) {
- throw new CAS_InvalidArgumentException(
- '$className must implement the CAS_Languages_LanguageInterface'
- );
- }
- $this->_lang = $lang;
- phpCAS::traceEnd();
- }
- /**
- * Create the language
- *
- * @return CAS_Languages_LanguageInterface object implementing the class
- */
- public function getLangObj()
- {
- $classname = $this->_lang;
- return new $classname();
- }
- /** @} */
- // ########################################################################
- // CAS SERVER CONFIG
- // ########################################################################
- /**
- * @addtogroup internalConfig
- * @{
- */
- /**
- * a record to store information about the CAS server.
- * - $_server['version']: the version of the CAS server
- * - $_server['hostname']: the hostname of the CAS server
- * - $_server['port']: the port the CAS server is running on
- * - $_server['uri']: the base URI the CAS server is responding on
- * - $_server['base_url']: the base URL of the CAS server
- * - $_server['login_url']: the login URL of the CAS server
- * - $_server['service_validate_url']: the service validating URL of the
- * CAS server
- * - $_server['proxy_url']: the proxy URL of the CAS server
- * - $_server['proxy_validate_url']: the proxy validating URL of the CAS server
- * - $_server['logout_url']: the logout URL of the CAS server
- *
- * $_server['version'], $_server['hostname'], $_server['port'] and
- * $_server['uri'] are written by CAS_Client::CAS_Client(), read by
- * CAS_Client::getServerVersion(), CAS_Client::_getServerHostname(),
- * CAS_Client::_getServerPort() and CAS_Client::_getServerURI().
- *
- * The other fields are written and read by CAS_Client::_getServerBaseURL(),
- * CAS_Client::getServerLoginURL(), CAS_Client::getServerServiceValidateURL(),
- * CAS_Client::getServerProxyValidateURL() and CAS_Client::getServerLogoutURL().
- *
- * @hideinitializer
- */
- private $_server = array(
- 'version' => '',
- 'hostname' => 'none',
- 'port' => -1,
- 'uri' => 'none');
- /**
- * This method is used to retrieve the version of the CAS server.
- *
- * @return string the version of the CAS server.
- */
- public function getServerVersion()
- {
- return $this->_server['version'];
- }
- /**
- * This method is used to retrieve the hostname of the CAS server.
- *
- * @return string the hostname of the CAS server.
- */
- private function _getServerHostname()
- {
- return $this->_server['hostname'];
- }
- /**
- * This method is used to retrieve the port of the CAS server.
- *
- * @return int the port of the CAS server.
- */
- private function _getServerPort()
- {
- return $this->_server['port'];
- }
- /**
- * This method is used to retrieve the URI of the CAS server.
- *
- * @return string a URI.
- */
- private function _getServerURI()
- {
- return $this->_server['uri'];
- }
- /**
- * This method is used to retrieve the base URL of the CAS server.
- *
- * @return string a URL.
- */
- private function _getServerBaseURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['base_url']) ) {
- $this->_server['base_url'] = 'https://' . $this->_getServerHostname();
- if ($this->_getServerPort()!=443) {
- $this->_server['base_url'] .= ':'
- .$this->_getServerPort();
- }
- $this->_server['base_url'] .= $this->_getServerURI();
- }
- return $this->_server['base_url'];
- }
- /**
- * This method is used to retrieve the login URL of the CAS server.
- *
- * @param bool $gateway true to check authentication, false to force it
- * @param bool $renew true to force the authentication with the CAS server
- *
- * @return string a URL.
- * @note It is recommended that CAS implementations ignore the "gateway"
- * parameter if "renew" is set
- */
- public function getServerLoginURL($gateway=false,$renew=false)
- {
- phpCAS::traceBegin();
- // the URL is build only when needed
- if ( empty($this->_server['login_url']) ) {
- $this->_server['login_url'] = $this->_buildQueryUrl($this->_getServerBaseURL().'login','service='.urlencode($this->getURL()));
- }
- $url = $this->_server['login_url'];
- if ($renew) {
- // It is recommended that when the "renew" parameter is set, its
- // value be "true"
- $url = $this->_buildQueryUrl($url, 'renew=true');
- } elseif ($gateway) {
- // It is recommended that when the "gateway" parameter is set, its
- // value be "true"
- $url = $this->_buildQueryUrl($url, 'gateway=true');
- }
- phpCAS::traceEnd($url);
- return $url;
- }
- /**
- * This method sets the login URL of the CAS server.
- *
- * @param string $url the login URL
- *
- * @return string login url
- */
- public function setServerLoginURL($url)
- {
- // Argument Validation
- if (gettype($url) != 'string')
- throw new CAS_TypeMismatchException($url, '$url', 'string');
- return $this->_server['login_url'] = $url;
- }
- /**
- * This method sets the serviceValidate URL of the CAS server.
- *
- * @param string $url the serviceValidate URL
- *
- * @return string serviceValidate URL
- */
- public function setServerServiceValidateURL($url)
- {
- // Argument Validation
- if (gettype($url) != 'string')
- throw new CAS_TypeMismatchException($url, '$url', 'string');
- return $this->_server['service_validate_url'] = $url;
- }
- /**
- * This method sets the proxyValidate URL of the CAS server.
- *
- * @param string $url the proxyValidate URL
- *
- * @return string proxyValidate URL
- */
- public function setServerProxyValidateURL($url)
- {
- // Argument Validation
- if (gettype($url) != 'string')
- throw new CAS_TypeMismatchException($url, '$url', 'string');
- return $this->_server['proxy_validate_url'] = $url;
- }
- /**
- * This method sets the samlValidate URL of the CAS server.
- *
- * @param string $url the samlValidate URL
- *
- * @return string samlValidate URL
- */
- public function setServerSamlValidateURL($url)
- {
- // Argument Validation
- if (gettype($url) != 'string')
- throw new CAS_TypeMismatchException($url, '$url', 'string');
- return $this->_server['saml_validate_url'] = $url;
- }
- /**
- * This method is used to retrieve the service validating URL of the CAS server.
- *
- * @return string serviceValidate URL.
- */
- public function getServerServiceValidateURL()
- {
- phpCAS::traceBegin();
- // the URL is build only when needed
- if ( empty($this->_server['service_validate_url']) ) {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- $this->_server['service_validate_url'] = $this->_getServerBaseURL()
- .'validate';
- break;
- case CAS_VERSION_2_0:
- $this->_server['service_validate_url'] = $this->_getServerBaseURL()
- .'serviceValidate';
- break;
- case CAS_VERSION_3_0:
- $this->_server['service_validate_url'] = $this->_getServerBaseURL()
- .'p3/serviceValidate';
- break;
- }
- }
- $url = $this->_buildQueryUrl(
- $this->_server['service_validate_url'],
- 'service='.urlencode($this->getURL())
- );
- phpCAS::traceEnd($url);
- return $url;
- }
- /**
- * This method is used to retrieve the SAML validating URL of the CAS server.
- *
- * @return string samlValidate URL.
- */
- public function getServerSamlValidateURL()
- {
- phpCAS::traceBegin();
- // the URL is build only when needed
- if ( empty($this->_server['saml_validate_url']) ) {
- switch ($this->getServerVersion()) {
- case SAML_VERSION_1_1:
- $this->_server['saml_validate_url'] = $this->_getServerBaseURL().'samlValidate';
- break;
- }
- }
- $url = $this->_buildQueryUrl(
- $this->_server['saml_validate_url'],
- 'TARGET='.urlencode($this->getURL())
- );
- phpCAS::traceEnd($url);
- return $url;
- }
- /**
- * This method is used to retrieve the proxy validating URL of the CAS server.
- *
- * @return string proxyValidate URL.
- */
- public function getServerProxyValidateURL()
- {
- phpCAS::traceBegin();
- // the URL is build only when needed
- if ( empty($this->_server['proxy_validate_url']) ) {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- $this->_server['proxy_validate_url'] = '';
- break;
- case CAS_VERSION_2_0:
- $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'proxyValidate';
- break;
- case CAS_VERSION_3_0:
- $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'p3/proxyValidate';
- break;
- }
- }
- $url = $this->_buildQueryUrl(
- $this->_server['proxy_validate_url'],
- 'service='.urlencode($this->getURL())
- );
- phpCAS::traceEnd($url);
- return $url;
- }
- /**
- * This method is used to retrieve the proxy URL of the CAS server.
- *
- * @return string proxy URL.
- */
- public function getServerProxyURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['proxy_url']) ) {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- $this->_server['proxy_url'] = '';
- break;
- case CAS_VERSION_2_0:
- case CAS_VERSION_3_0:
- $this->_server['proxy_url'] = $this->_getServerBaseURL().'proxy';
- break;
- }
- }
- return $this->_server['proxy_url'];
- }
- /**
- * This method is used to retrieve the logout URL of the CAS server.
- *
- * @return string logout URL.
- */
- public function getServerLogoutURL()
- {
- // the URL is build only when needed
- if ( empty($this->_server['logout_url']) ) {
- $this->_server['logout_url'] = $this->_getServerBaseURL().'logout';
- }
- return $this->_server['logout_url'];
- }
- /**
- * This method sets the logout URL of the CAS server.
- *
- * @param string $url the logout URL
- *
- * @return string logout url
- */
- public function setServerLogoutURL($url)
- {
- // Argument Validation
- if (gettype($url) != 'string')
- throw new CAS_TypeMismatchException($url, '$url', 'string');
- return $this->_server['logout_url'] = $url;
- }
- /**
- * An array to store extra curl options.
- */
- private $_curl_options = array();
- /**
- * This method is used to set additional user curl options.
- *
- * @param string $key name of the curl option
- * @param string $value value of the curl option
- *
- * @return void
- */
- public function setExtraCurlOption($key, $value)
- {
- $this->_curl_options[$key] = $value;
- }
- /** @} */
- // ########################################################################
- // Change the internal behaviour of phpcas
- // ########################################################################
- /**
- * @addtogroup internalBehave
- * @{
- */
- /**
- * The class to instantiate for making web requests in readUrl().
- * The class specified must implement the CAS_Request_RequestInterface.
- * By default CAS_Request_CurlRequest is used, but this may be overridden to
- * supply alternate request mechanisms for testing.
- */
- private $_requestImplementation = 'CAS_Request_CurlRequest';
- /**
- * Override the default implementation used to make web requests in readUrl().
- * This class must implement the CAS_Request_RequestInterface.
- *
- * @param string $className name of the RequestImplementation class
- *
- * @return void
- */
- public function setRequestImplementation ($className)
- {
- $obj = new $className;
- if (!($obj instanceof CAS_Request_RequestInterface)) {
- throw new CAS_InvalidArgumentException(
- '$className must implement the CAS_Request_RequestInterface'
- );
- }
- $this->_requestImplementation = $className;
- }
- /**
- * @var boolean $_clearTicketsFromUrl; If true, phpCAS will clear session
- * tickets from the URL after a successful authentication.
- */
- private $_clearTicketsFromUrl = true;
- /**
- * Configure the client to not send redirect headers and call exit() on
- * authentication success. The normal redirect is used to remove the service
- * ticket from the client's URL, but for running unit tests we need to
- * continue without exiting.
- *
- * Needed for testing authentication
- *
- * @return void
- */
- public function setNoClearTicketsFromUrl ()
- {
- $this->_clearTicketsFromUrl = false;
- }
- /**
- * @var callback $_attributeParserCallbackFunction;
- */
- private $_casAttributeParserCallbackFunction = null;
- /**
- * @var array $_attributeParserCallbackArgs;
- */
- private $_casAttributeParserCallbackArgs = array();
- /**
- * Set a callback function to be run when parsing CAS attributes
- *
- * The callback function will be passed a XMLNode as its first parameter,
- * followed by any $additionalArgs you pass.
- *
- * @param string $function callback function to call
- * @param array $additionalArgs optional array of arguments
- *
- * @return void
- */
- public function setCasAttributeParserCallback($function, array $additionalArgs = array())
- {
- $this->_casAttributeParserCallbackFunction = $function;
- $this->_casAttributeParserCallbackArgs = $additionalArgs;
- }
- /** @var callable $_postAuthenticateCallbackFunction;
- */
- private $_postAuthenticateCallbackFunction = null;
- /**
- * @var array $_postAuthenticateCallbackArgs;
- */
- private $_postAuthenticateCallbackArgs = array();
- /**
- * Set a callback function to be run when a user authenticates.
- *
- * The callback function will be passed a $logoutTicket as its first parameter,
- * followed by any $additionalArgs you pass. The $logoutTicket parameter is an
- * opaque string that can be used to map a session-id to the logout request
- * in order to support single-signout in applications that manage their own
- * sessions (rather than letting phpCAS start the session).
- *
- * phpCAS::forceAuthentication() will always exit and forward client unless
- * they are already authenticated. To perform an action at the moment the user
- * logs in (such as registering an account, performing logging, etc), register
- * a callback function here.
- *
- * @param callable $function callback function to call
- * @param array $additionalArgs optional array of arguments
- *
- * @return void
- */
- public function setPostAuthenticateCallback ($function, array $additionalArgs = array())
- {
- $this->_postAuthenticateCallbackFunction = $function;
- $this->_postAuthenticateCallbackArgs = $additionalArgs;
- }
- /**
- * @var callable $_signoutCallbackFunction;
- */
- private $_signoutCallbackFunction = null;
- /**
- * @var array $_signoutCallbackArgs;
- */
- private $_signoutCallbackArgs = array();
- /**
- * Set a callback function to be run when a single-signout request is received.
- *
- * The callback function will be passed a $logoutTicket as its first parameter,
- * followed by any $additionalArgs you pass. The $logoutTicket parameter is an
- * opaque string that can be used to map a session-id to the logout request in
- * order to support single-signout in applications that manage their own sessions
- * (rather than letting phpCAS start and destroy the session).
- *
- * @param callable $function callback function to call
- * @param array $additionalArgs optional array of arguments
- *
- * @return void
- */
- public function setSingleSignoutCallback ($function, array $additionalArgs = array())
- {
- $this->_signoutCallbackFunction = $function;
- $this->_signoutCallbackArgs = $additionalArgs;
- }
- // ########################################################################
- // Methods for supplying code-flow feedback to integrators.
- // ########################################################################
- /**
- * Ensure that this is actually a proxy object or fail with an exception
- *
- * @throws CAS_OutOfSequenceBeforeProxyException
- *
- * @return void
- */
- public function ensureIsProxy()
- {
- if (!$this->isProxy()) {
- throw new CAS_OutOfSequenceBeforeProxyException();
- }
- }
- /**
- * Mark the caller of authentication. This will help client integraters determine
- * problems with their code flow if they call a function such as getUser() before
- * authentication has occurred.
- *
- * @param bool $auth True if authentication was successful, false otherwise.
- *
- * @return null
- */
- public function markAuthenticationCall ($auth)
- {
- // store where the authentication has been checked and the result
- $dbg = debug_backtrace();
- $this->_authentication_caller = array (
- 'file' => $dbg[1]['file'],
- 'line' => $dbg[1]['line'],
- 'method' => $dbg[1]['class'] . '::' . $dbg[1]['function'],
- 'result' => (boolean)$auth
- );
- }
- private $_authentication_caller;
- /**
- * Answer true if authentication has been checked.
- *
- * @return bool
- */
- public function wasAuthenticationCalled ()
- {
- return !empty($this->_authentication_caller);
- }
- /**
- * Ensure that authentication was checked. Terminate with exception if no
- * authentication was performed
- *
- * @throws CAS_OutOfSequenceBeforeAuthenticationCallException
- *
- * @return void
- */
- private function _ensureAuthenticationCalled()
- {
- if (!$this->wasAuthenticationCalled()) {
- throw new CAS_OutOfSequenceBeforeAuthenticationCallException();
- }
- }
- /**
- * Answer the result of the authentication call.
- *
- * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
- * and markAuthenticationCall() didn't happen.
- *
- * @return bool
- */
- public function wasAuthenticationCallSuccessful ()
- {
- $this->_ensureAuthenticationCalled();
- return $this->_authentication_caller['result'];
- }
- /**
- * Ensure that authentication was checked. Terminate with exception if no
- * authentication was performed
- *
- * @throws CAS_OutOfSequenceException
- *
- * @return void
- */
- public function ensureAuthenticationCallSuccessful()
- {
- $this->_ensureAuthenticationCalled();
- if (!$this->_authentication_caller['result']) {
- throw new CAS_OutOfSequenceException(
- 'authentication was checked (by '
- . $this->getAuthenticationCallerMethod()
- . '() at ' . $this->getAuthenticationCallerFile()
- . ':' . $this->getAuthenticationCallerLine()
- . ') but the method returned false'
- );
- }
- }
- /**
- * Answer information about the authentication caller.
- *
- * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
- * and markAuthenticationCall() didn't happen.
- *
- * @return string the file that called authentication
- */
- public function getAuthenticationCallerFile ()
- {
- $this->_ensureAuthenticationCalled();
- return $this->_authentication_caller['file'];
- }
- /**
- * Answer information about the authentication caller.
- *
- * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
- * and markAuthenticationCall() didn't happen.
- *
- * @return int the line that called authentication
- */
- public function getAuthenticationCallerLine ()
- {
- $this->_ensureAuthenticationCalled();
- return $this->_authentication_caller['line'];
- }
- /**
- * Answer information about the authentication caller.
- *
- * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
- * and markAuthenticationCall() didn't happen.
- *
- * @return string the method that called authentication
- */
- public function getAuthenticationCallerMethod ()
- {
- $this->_ensureAuthenticationCalled();
- return $this->_authentication_caller['method'];
- }
- /** @} */
- // ########################################################################
- // CONSTRUCTOR
- // ########################################################################
- /**
- * @addtogroup internalConfig
- * @{
- */
- /**
- * CAS_Client constructor.
- *
- * @param string $server_version the version of the CAS server
- * @param bool $proxy true if the CAS client is a CAS proxy
- * @param string $server_hostname the hostname of the CAS server
- * @param int $server_port the port the CAS server is running on
- * @param string $server_uri the URI the CAS server is responding on
- * @param bool $changeSessionID Allow phpCAS to change the session_id
- * (Single Sign Out/handleLogoutRequests
- * is based on that change)
- *
- * @return self a newly created CAS_Client object
- */
- public function __construct(
- $server_version,
- $proxy,
- $server_hostname,
- $server_port,
- $server_uri,
- $changeSessionID = true
- ) {
- // Argument validation
- if (gettype($server_version) != 'string')
- throw new CAS_TypeMismatchException($server_version, '$server_version', 'string');
- if (gettype($proxy) != 'boolean')
- throw new CAS_TypeMismatchException($proxy, '$proxy', 'boolean');
- if (gettype($server_hostname) != 'string')
- throw new CAS_TypeMismatchException($server_hostname, '$server_hostname', 'string');
- if (gettype($server_port) != 'integer')
- throw new CAS_TypeMismatchException($server_port, '$server_port', 'integer');
- if (gettype($server_uri) != 'string')
- throw new CAS_TypeMismatchException($server_uri, '$server_uri', 'string');
- if (gettype($changeSessionID) != 'boolean')
- throw new CAS_TypeMismatchException($changeSessionID, '$changeSessionID', 'boolean');
- phpCAS::traceBegin();
- // true : allow to change the session_id(), false session_id won't be
- // change and logout won't be handle because of that
- $this->_setChangeSessionID($changeSessionID);
- // skip Session Handling for logout requests and if don't want it'
- if (session_id()=="" && !$this->_isLogoutRequest()) {
- session_start();
- phpCAS :: trace("Starting a new session " . session_id());
- }
- // Only for debug purposes
- if ($this->isSessionAuthenticated()){
- phpCAS :: trace("Session is authenticated as: " . $_SESSION['phpCAS']['user']);
- } else {
- phpCAS :: trace("Session is not authenticated");
- }
- // are we in proxy mode ?
- $this->_proxy = $proxy;
- // Make cookie handling available.
- if ($this->isProxy()) {
- if (!isset($_SESSION['phpCAS'])) {
- $_SESSION['phpCAS'] = array();
- }
- if (!isset($_SESSION['phpCAS']['service_cookies'])) {
- $_SESSION['phpCAS']['service_cookies'] = array();
- }
- $this->_serviceCookieJar = new CAS_CookieJar(
- $_SESSION['phpCAS']['service_cookies']
- );
- }
- // check version
- $supportedProtocols = phpCAS::getSupportedProtocols();
- if (isset($supportedProtocols[$server_version]) === false) {
- phpCAS::error(
- 'this version of CAS (`'.$server_version
- .'\') is not supported by phpCAS '.phpCAS::getVersion()
- );
- }
- if ($server_version === CAS_VERSION_1_0 && $this->isProxy()) {
- phpCAS::error(
- 'CAS proxies are not supported in CAS '.$server_version
- );
- }
- $this->_server['version'] = $server_version;
- // check hostname
- if ( empty($server_hostname)
- || !preg_match('/[\.\d\-a-z]*/', $server_hostname)
- ) {
- phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
- }
- $this->_server['hostname'] = $server_hostname;
- // check port
- if ( $server_port == 0
- || !is_int($server_port)
- ) {
- phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
- }
- $this->_server['port'] = $server_port;
- // check URI
- if ( !preg_match('/[\.\d\-_a-z\/]*/', $server_uri) ) {
- phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
- }
- // add leading and trailing `/' and remove doubles
- if(strstr($server_uri, '?') === false) $server_uri .= '/';
- $server_uri = preg_replace('/\/\//', '/', '/'.$server_uri);
- $this->_server['uri'] = $server_uri;
- // set to callback mode if PgtIou and PgtId CGI GET parameters are provided
- if ( $this->isProxy() ) {
- if(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId'])) {
- $this->_setCallbackMode(true);
- $this->_setCallbackModeUsingPost(false);
- } elseif (!empty($_POST['pgtIou'])&&!empty($_POST['pgtId'])) {
- $this->_setCallbackMode(true);
- $this->_setCallbackModeUsingPost(true);
- } else {
- $this->_setCallbackMode(false);
- $this->_setCallbackModeUsingPost(false);
- }
-
- }
- if ( $this->_isCallbackMode() ) {
- //callback mode: check that phpCAS is secured
- if ( !$this->_isHttps() ) {
- phpCAS::error(
- 'CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server'
- );
- }
- } else {
- //normal mode: get ticket and remove it from CGI parameters for
- // developers
- $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
- if (preg_match('/^[SP]T-/', $ticket) ) {
- phpCAS::trace('Ticket \''.$ticket.'\' found');
- $this->setTicket($ticket);
- unset($_GET['ticket']);
- } else if ( !empty($ticket) ) {
- //ill-formed ticket, halt
- phpCAS::error(
- 'ill-formed ticket found in the URL (ticket=`'
- .htmlentities($ticket).'\')'
- );
- }
- }
- phpCAS::traceEnd();
- }
- /** @} */
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX Session Handling XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- /**
- * @addtogroup internalConfig
- * @{
- */
- /**
- * @var bool A variable to whether phpcas will use its own session handling. Default = true
- * @hideinitializer
- */
- private $_change_session_id = true;
- /**
- * Set a parameter whether to allow phpCAS to change session_id
- *
- * @param bool $allowed allow phpCAS to change session_id
- *
- * @return void
- */
- private function _setChangeSessionID($allowed)
- {
- $this->_change_session_id = $allowed;
- }
- /**
- * Get whether phpCAS is allowed to change session_id
- *
- * @return bool
- */
- public function getChangeSessionID()
- {
- return $this->_change_session_id;
- }
- /** @} */
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX AUTHENTICATION XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- /**
- * @addtogroup internalAuthentication
- * @{
- */
- /**
- * The Authenticated user. Written by CAS_Client::_setUser(), read by
- * CAS_Client::getUser().
- *
- * @hideinitializer
- */
- private $_user = '';
- /**
- * This method sets the CAS user's login name.
- *
- * @param string $user the login name of the authenticated user.
- *
- * @return void
- */
- private function _setUser($user)
- {
- $this->_user = $user;
- }
- /**
- * This method returns the CAS user's login name.
- *
- * @return string the login name of the authenticated user
- *
- * @warning should be called only after CAS_Client::forceAuthentication() or
- * CAS_Client::isAuthenticated(), otherwise halt with an error.
- */
- public function getUser()
- {
- // Sequence validation
- $this->ensureAuthenticationCallSuccessful();
- return $this->_getUser();
- }
- /**
- * This method returns the CAS user's login name.
- *
- * @return string the login name of the authenticated user
- *
- * @warning should be called only after CAS_Client::forceAuthentication() or
- * CAS_Client::isAuthenticated(), otherwise halt with an error.
- */
- private function _getUser()
- {
- // This is likely a duplicate check that could be removed....
- if ( empty($this->_user) ) {
- phpCAS::error(
- 'this method should be used only after '.__CLASS__
- .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
- );
- }
- return $this->_user;
- }
- /**
- * The Authenticated users attributes. Written by
- * CAS_Client::setAttributes(), read by CAS_Client::getAttributes().
- * @attention client applications should use phpCAS::getAttributes().
- *
- * @hideinitializer
- */
- private $_attributes = array();
- /**
- * Set an array of attributes
- *
- * @param array $attributes a key value array of attributes
- *
- * @return void
- */
- public function setAttributes($attributes)
- {
- $this->_attributes = $attributes;
- }
- /**
- * Get an key values arry of attributes
- *
- * @return array of attributes
- */
- public function getAttributes()
- {
- // Sequence validation
- $this->ensureAuthenticationCallSuccessful();
- // This is likely a duplicate check that could be removed....
- if ( empty($this->_user) ) {
- // if no user is set, there shouldn't be any attributes also...
- phpCAS::error(
- 'this method should be used only after '.__CLASS__
- .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
- );
- }
- return $this->_attributes;
- }
- /**
- * Check whether attributes are available
- *
- * @return bool attributes available
- */
- public function hasAttributes()
- {
- // Sequence validation
- $this->ensureAuthenticationCallSuccessful();
- return !empty($this->_attributes);
- }
- /**
- * Check whether a specific attribute with a name is available
- *
- * @param string $key name of attribute
- *
- * @return bool is attribute available
- */
- public function hasAttribute($key)
- {
- // Sequence validation
- $this->ensureAuthenticationCallSuccessful();
- return $this->_hasAttribute($key);
- }
- /**
- * Check whether a specific attribute with a name is available
- *
- * @param string $key name of attribute
- *
- * @return bool is attribute available
- */
- private function _hasAttribute($key)
- {
- return (is_array($this->_attributes)
- && array_key_exists($key, $this->_attributes));
- }
- /**
- * Get a specific attribute by name
- *
- * @param string $key name of attribute
- *
- * @return string attribute values
- */
- public function getAttribute($key)
- {
- // Sequence validation
- $this->ensureAuthenticationCallSuccessful();
- if ($this->_hasAttribute($key)) {
- return $this->_attributes[$key];
- }
- }
- /**
- * This method is called to renew the authentication of the user
- * If the user is authenticated, renew the connection
- * If not, redirect to CAS
- *
- * @return bool true when the user is authenticated; otherwise halt.
- */
- public function renewAuthentication()
- {
- phpCAS::traceBegin();
- // Either way, the user is authenticated by CAS
- if (isset( $_SESSION['phpCAS']['auth_checked'])) {
- unset($_SESSION['phpCAS']['auth_checked']);
- }
- if ( $this->isAuthenticated(true) ) {
- phpCAS::trace('user already authenticated');
- $res = true;
- } else {
- $this->redirectToCas(false, true);
- // never reached
- $res = false;
- }
- phpCAS::traceEnd();
- return $res;
- }
- /**
- * This method is called to be sure that the user is authenticated. When not
- * authenticated, halt by redirecting to the CAS server; otherwise return true.
- *
- * @return bool true when the user is authenticated; otherwise halt.
- */
- public function forceAuthentication()
- {
- phpCAS::traceBegin();
- if ( $this->isAuthenticated() ) {
- // the user is authenticated, nothing to be done.
- phpCAS::trace('no need to authenticate');
- $res = true;
- } else {
- // the user is not authenticated, redirect to the CAS server
- if (isset($_SESSION['phpCAS']['auth_checked'])) {
- unset($_SESSION['phpCAS']['auth_checked']);
- }
- $this->redirectToCas(false/* no gateway */);
- // never reached
- $res = false;
- }
- phpCAS::traceEnd($res);
- return $res;
- }
- /**
- * An integer that gives the number of times authentication will be cached
- * before rechecked.
- *
- * @hideinitializer
- */
- private $_cache_times_for_auth_recheck = 0;
- /**
- * Set the number of times authentication will be cached before rechecked.
- *
- * @param int $n number of times to wait for a recheck
- *
- * @return void
- */
- public function setCacheTimesForAuthRecheck($n)
- {
- if (gettype($n) != 'integer')
- throw new CAS_TypeMismatchException($n, '$n', 'string');
- $this->_cache_times_for_auth_recheck = $n;
- }
- /**
- * This method is called to check whether the user is authenticated or not.
- *
- * @return bool true when the user is authenticated, false when a previous
- * gateway login failed or the function will not return if the user is
- * redirected to the cas server for a gateway login attempt
- */
- public function checkAuthentication()
- {
- phpCAS::traceBegin();
- if ( $this->isAuthenticated() ) {
- phpCAS::trace('user is authenticated');
- /* The 'auth_checked' variable is removed just in case it's set. */
- unset($_SESSION['phpCAS']['auth_checked']);
- $res = true;
- } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
- // the previous request has redirected the client to the CAS server
- // with gateway=true
- unset($_SESSION['phpCAS']['auth_checked']);
- $res = false;
- } else {
- // avoid a check against CAS on every request
- if (!isset($_SESSION['phpCAS']['unauth_count'])) {
- $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
- }
- if (($_SESSION['phpCAS']['unauth_count'] != -2
- && $this->_cache_times_for_auth_recheck == -1)
- || ($_SESSION['phpCAS']['unauth_count'] >= 0
- && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck)
- ) {
- $res = false;
- if ($this->_cache_times_for_auth_recheck != -1) {
- $_SESSION['phpCAS']['unauth_count']++;
- phpCAS::trace(
- 'user is not authenticated (cached for '
- .$_SESSION['phpCAS']['unauth_count'].' times of '
- .$this->_cache_times_for_auth_recheck.')'
- );
- } else {
- phpCAS::trace(
- 'user is not authenticated (cached for until login pressed)'
- );
- }
- } else {
- $_SESSION['phpCAS']['unauth_count'] = 0;
- $_SESSION['phpCAS']['auth_checked'] = true;
- phpCAS::trace('user is not authenticated (cache reset)');
- $this->redirectToCas(true/* gateway */);
- // never reached
- $res = false;
- }
- }
- phpCAS::traceEnd($res);
- return $res;
- }
- /**
- * This method is called to check if the user is authenticated (previously or by
- * tickets given in the URL).
- *
- * @param bool $renew true to force the authentication with the CAS server
- *
- * @return bool true when the user is authenticated. Also may redirect to the
- * same URL without the ticket.
- */
- public function isAuthenticated($renew=false)
- {
- phpCAS::traceBegin();
- $res = false;
- $validate_url = '';
- if ( $this->_wasPreviouslyAuthenticated() ) {
- if ($this->hasTicket()) {
- // User has a additional ticket but was already authenticated
- phpCAS::trace(
- 'ticket was present and will be discarded, use renewAuthenticate()'
- );
- if ($this->_clearTicketsFromUrl) {
- phpCAS::trace("Prepare redirect to : ".$this->getURL());
- session_write_close();
- header('Location: '.$this->getURL());
- flush();
- phpCAS::traceExit();
- throw new CAS_GracefullTerminationException();
- } else {
- phpCAS::trace(
- 'Already authenticated, but skipping ticket clearing since setNoClearTicketsFromUrl() was used.'
- );
- $res = true;
- }
- } else {
- // the user has already (previously during the session) been
- // authenticated, nothing to be done.
- phpCAS::trace(
- 'user was already authenticated, no need to look for tickets'
- );
- $res = true;
- }
- // Mark the auth-check as complete to allow post-authentication
- // callbacks to make use of phpCAS::getUser() and similar methods
- $this->markAuthenticationCall($res);
- } else {
- if ($this->hasTicket()) {
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- // if a Service Ticket was given, validate it
- phpCAS::trace(
- 'CAS 1.0 ticket `'.$this->getTicket().'\' is present'
- );
- $this->validateCAS10(
- $validate_url, $text_response, $tree_response, $renew
- ); // if it fails, it halts
- phpCAS::trace(
- 'CAS 1.0 ticket `'.$this->getTicket().'\' was validated'
- );
- $_SESSION['phpCAS']['user'] = $this->_getUser();
- $res = true;
- $logoutTicket = $this->getTicket();
- break;
- case CAS_VERSION_2_0:
- case CAS_VERSION_3_0:
- // if a Proxy Ticket was given, validate it
- phpCAS::trace(
- 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' is present'
- );
- $this->validateCAS20(
- $validate_url, $text_response, $tree_response, $renew
- ); // note: if it fails, it halts
- phpCAS::trace(
- 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' was validated'
- );
- if ( $this->isProxy() ) {
- $this->_validatePGT(
- $validate_url, $text_response, $tree_response
- ); // idem
- phpCAS::trace('PGT `'.$this->_getPGT().'\' was validated');
- $_SESSION['phpCAS']['pgt'] = $this->_getPGT();
- }
- $_SESSION['phpCAS']['user'] = $this->_getUser();
- if (!empty($this->_attributes)) {
- $_SESSION['phpCAS']['attributes'] = $this->_attributes;
- }
- $proxies = $this->getProxies();
- if (!empty($proxies)) {
- $_SESSION['phpCAS']['proxies'] = $this->getProxies();
- }
- $res = true;
- $logoutTicket = $this->getTicket();
- break;
- case SAML_VERSION_1_1:
- // if we have a SAML ticket, validate it.
- phpCAS::trace(
- 'SAML 1.1 ticket `'.$this->getTicket().'\' is present'
- );
- $this->validateSA(
- $validate_url, $text_response, $tree_response, $renew
- ); // if it fails, it halts
- phpCAS::trace(
- 'SAML 1.1 ticket `'.$this->getTicket().'\' was validated'
- );
- $_SESSION['phpCAS']['user'] = $this->_getUser();
- …
Large files files are truncated, but you can click here to view the full file