diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/papi/default-disable | 0 | ||||
-rw-r--r-- | modules/papi/docs/papi.txt | 43 | ||||
-rw-r--r-- | modules/papi/lib/Auth/Source/PAPI.php | 174 |
3 files changed, 217 insertions, 0 deletions
diff --git a/modules/papi/default-disable b/modules/papi/default-disable new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/modules/papi/default-disable diff --git a/modules/papi/docs/papi.txt b/modules/papi/docs/papi.txt new file mode 100644 index 0000000..2180206 --- /dev/null +++ b/modules/papi/docs/papi.txt @@ -0,0 +1,43 @@ +PAPI module +=========== + +The PAPI module provides a single authentication module: + +`papi:PAPI` +: Authenticate using the PAPI protocol. + +This authentication module makes use of an external library, phpPoA, in order to +authenticate users by means of the PAPI protocol. It can therefore +be used to bridge between protocols, behaving like a PAPI `Point of Access` or +Service Provider. + +To use this module, enable it by creating a file named `enable` in the +`modules/papi/` directory. Then you need to add an authentication source which +makes use of the `papi:PAPI` module to the `config/authsources.php` file: + + 'example-papi' => array( + 'papi:PAPI', + + /* + * The site identifier that allows the module to determine which + * configuration of the phpPoA to use. + */ + 'site' => 'example', + + /* + * The Home Locator Identifier. Use this if your phpPoA configuration + * points to a GPoA instead of an Authentication Server (AS), and you + * want to skip the identity provider selection page, by directly + * selecting one here. + */ + 'hli' => 'exampleAS', + ), + +User attributes +--------------- + +If user attributes were received upon succesful authentication, then their exact +names and values will be transferred into the $state['Attributes'] array. Please +note that attribute name mapping could be needed. There's no support for asking +specific attributes during PAPI authentication. Attributes released to a Service +Provider must be agreed and configured on beforehand.
\ No newline at end of file diff --git a/modules/papi/lib/Auth/Source/PAPI.php b/modules/papi/lib/Auth/Source/PAPI.php new file mode 100644 index 0000000..ead66c8 --- /dev/null +++ b/modules/papi/lib/Auth/Source/PAPI.php @@ -0,0 +1,174 @@ +<?php + +/** + * Authenticate using PAPI protocol. + * + * @author Jaime Perez, RedIRIS + * @package simpleSAMLphp + * @version $Id$ + */ +include("poa2/PoA.php"); + +class sspmod_papi_Auth_Source_PAPI extends SimpleSAML_Auth_Source { + + /** + * The string used to identify our states. + */ + const STAGE_INIT = 'sspmod_papi_Auth_Source_PAPI.state'; + + /** + * The key of the AuthId field in the state. + */ + const AUTHID = 'sspmod_papi_Auth_Source_PAPI.AuthId'; + + /** + * @var the PoA to use. + */ + private $_poa; + + /** + * @var the home locator interface to use. + */ + private $_hli; + + /** + * @var the PAPIOPOA to use. + */ + private $_papiopoa; + + /** + * @var the attributes of the user. + */ + private $_attrs; + + /** + * @var the state ID to retrieve the original request later. + */ + private $_stateId; + + /** + * Constructor for this authentication source. + * + * @param array $info Information about this authentication source. + * @param array $config Configuration. + */ + public function __construct($info, $config) { + assert('is_array($info)'); + assert('is_array($config)'); + + /* Call the parent constructor first, as required by the interface. */ + parent::__construct($info, $config); + + if (!array_key_exists('site', $config)) { + throw new Exception('PAPI authentication source is not properly configured: missing [site]'); + } + $this->_poa = new PoA($config['site']); + + if (array_key_exists('hli', $config)) { + $this->_hli = $config['hli']; + } + + } + + /** + * Hook that will set Home Locator Identifier, PAPIOPOA and/or State ID. + * + * @param The PAPI request parameters that will be modified/extended. + */ + public function modifyParams(&$params) { + if (!empty($this->_hli)) { + $params['PAPIHLI'] = $this->_hli; + } + if (!empty($this->_papiopoa)) { + $params['PAPIOPOA'] = $this->_papiopoa; + } + $params['URL'] = $params['URL'].urlencode("&SSPStateID=".$this->_stateId); + return false; + } + + /** + * Parse the attribute array in a format suitable for SSP. + * + * @param the original attribute array. + */ + protected function parseAttributes($attrs) { + assert('is_array($attrs)'); + + foreach ($attrs as $name => $value) { + if (!is_array($value)) { + $attrs[$name] = array($value); + } + } + return $attrs; + } + + /** + * Log-in using PAPI + * + * @param array &$state Information about the current authentication. + */ + public function authenticate(&$state) { + assert('is_array($state)'); + $this->_papiopoa = $state['SPMetadata']['entityid']; + + // check if we are returning back from PAPI authentication + if (isset($_REQUEST['SSPStateID'])) { + // yes! restore original request + $this->_stateId = (string)$_REQUEST['SSPStateID']; + $state = SimpleSAML_Auth_State::loadState($this->_stateId, self::STAGE_INIT); + } else if (!$this->_poa->isAuthenticated()) { + // no! we have to save the request + + /* We are will need the authId in order to retrieve this authentication source later. */ + $state[self::AUTHID] = $this->authId; + $this->_stateId = SimpleSAML_Auth_State::saveState($state, self::STAGE_INIT); + + $this->_poa->addHook("PAPI_REDIRECT_URL_FINISH", new Hook(array($this, "modifyParams"))); + } + + $this->_poa->authenticate(); + $this->_attrs = $this->_poa->getAttributes(); + $state['Attributes'] = $this->parseAttributes($this->_attrs); + self::completeAuth($state); + } + + /** + * Log out from this authentication source. + * + * This function should be overridden if the authentication source requires special + * steps to complete a logout operation. + * + * If the logout process requires a redirect, the state should be saved. Once the + * logout operation is completed, the state should be restored, and completeLogout + * should be called with the state. If this operation can be completed without + * showing the user a page, or redirecting, this function should return. + * + * @param array &$state Information about the current logout operation. + */ + public function logout(&$state) { + assert('is_array($state)'); + + // check first if we have a valid session + if ($this->_poa->isAuthenticated()) { + /* We are will need the authId in order to retrieve this authentication source later. */ + $state[self::AUTHID] = $this->authId; + $this->_stateId = SimpleSAML_Auth_State::saveState($state, self::STAGE_INIT); + + // TODO: pending on phpPoA adding PAPI_SLO_REDIRECT_URL_FINISH hook + $this->_poa->addHook("PAPI_SLO_REDIRECT_URL_FINISH", new Hook(array($this, "modifyParams"))); + + // perform single logout, this won't return + $this->_poa->logout(true); + } else if (isset($_REQUEST['SSPStateID'])) { + $this->_stateId = (string)$_REQUEST['SSPStateID']; + $state = SimpleSAML_Auth_State::loadState($this->_stateId, self::STAGE_INIT); + } else { + return; + } + + self::completeLogout($state); + } + +} + +?> |