summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlav Morken <olav.morken@uninett.no>2008-08-18 11:38:10 +0000
committerOlav Morken <olav.morken@uninett.no>2008-08-18 11:38:10 +0000
commitd1683bdba81dd7be992644025c908196bd3558af (patch)
treea5bb0480c9f42828d34edb26338c0e33d24f8c6d
parentc1c2c004eb46ffabc3a61f3196d31a9600b34edc (diff)
downloadsimplesamlphp-d1683bdba81dd7be992644025c908196bd3558af.zip
simplesamlphp-d1683bdba81dd7be992644025c908196bd3558af.tar.gz
simplesamlphp-d1683bdba81dd7be992644025c908196bd3558af.tar.bz2
Authentication processing filters.
git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@811 44740490-163a-0410-bde0-09ae8108e29a
-rw-r--r--lib/SimpleSAML/Auth/ProcessingChain.php218
-rw-r--r--lib/SimpleSAML/Auth/ProcessingFilter.php69
-rw-r--r--modules/core/default-enable3
-rw-r--r--modules/core/lib/Auth/Process/AttributeAdd.php113
-rw-r--r--modules/core/lib/Auth/Process/AttributeLimit.php70
-rw-r--r--modules/core/lib/Auth/Process/AttributeMap.php108
-rw-r--r--modules/exampleauth/lib/Auth/Process/RedirectTest.php30
-rw-r--r--modules/exampleauth/www/redirecttest.php22
-rw-r--r--www/saml2/idp/SSOService.php35
-rw-r--r--www/shib13/idp/SSOService.php35
10 files changed, 703 insertions, 0 deletions
diff --git a/lib/SimpleSAML/Auth/ProcessingChain.php b/lib/SimpleSAML/Auth/ProcessingChain.php
new file mode 100644
index 0000000..4ba54ba
--- /dev/null
+++ b/lib/SimpleSAML/Auth/ProcessingChain.php
@@ -0,0 +1,218 @@
+<?php
+
+/**
+ * Class for implementing authentication processing chains for IdPs.
+ *
+ * This class implements a system for additional steps which should be taken by an IdP before
+ * submitting a response to a SP. Examples of additional steps can be additional authentication
+ * checks, or attribute consent requirements.
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class SimpleSAML_Auth_ProcessingChain {
+
+
+ /**
+ * The list of remaining filters which should be applied to the state.
+ */
+ const FILTERS_INDEX = 'SimpleSAML_Auth_ProcessingChain.filters';
+
+
+ /**
+ * The stage we use for completed requests.
+ */
+ const COMPLETED_STAGE = 'SimpleSAML_Auth_ProcessingChain.completed';
+
+
+ /**
+ * The request parameter we will use to pass the state identifier when we redirect after
+ * having completed processing of the state.
+ */
+ const AUTHPARAM = 'AuthProcId';
+
+
+ /**
+ * All authentication processing filters, in the order they should be applied.
+ */
+ private $filters;
+
+
+ /**
+ * Initialize an authentication processing chain for the given service provider
+ * and identity provider.
+ *
+ * @param array $idpMetadata The metadata for the IdP.
+ * @param array $spMetadata The metadata for the SP.
+ */
+ public function __construct($idpMetadata, $spMetadata) {
+ assert('is_array($idpMetadata)');
+ assert('is_array($spMetadata)');
+
+ $this->filters = array();
+
+ if (array_key_exists('authproc', $idpMetadata)) {
+ $idpFilters = self::parseFilterList($idpMetadata['authproc']);
+ self::addFilters($this->filters, $idpFilters);
+ }
+
+ if (array_key_exists('authproc', $spMetadata)) {
+ $spFilters = self::parseFilterList($spMetadata['authproc']);
+ self::addFilters($this->filters, $spFilters);
+ }
+
+
+ SimpleSAML_Logger::debug('Filter config for ' . $idpMetadata['entityid'] . '->' .
+ $spMetadata['entityid'] . ': ' . str_replace("\n", '', var_export($this->filters, TRUE)));
+
+ }
+
+
+ /**
+ * Sort & merge filter configuration
+ *
+ * Inserts unsorted filters into sorted filter list. This sort operation is stable.
+ *
+ * @param array &$target Target filter list. This list must be sorted.
+ * @param array $src Source filters. May be unsorted.
+ */
+ private static function addFilters(&$target, $src) {
+ assert('is_array($target)');
+ assert('is_array($src)');
+
+ foreach ($src as $filter) {
+ $fp = $filter->priority;
+
+ /* Find insertion position for filter. */
+ for($i = count($target)-1; $i >= 0; $i--) {
+ if ($target[$i]->priority <= $fp) {
+ /* The new filter should be inserted after this one. */
+ break;
+ }
+ }
+ /* $i now points to the filter which should preceede the current filter. */
+ array_splice($target, $i+1, 0, array($filter));
+ }
+
+ }
+
+
+ /**
+ * Parse an array of authentication processing filters.
+ *
+ * @param array $filterSrc Array with filter configuration.
+ * @return array Array of SimpleSAML_Auth_ProcessingFilter objects.
+ */
+ private static function parseFilterList($filterSrc) {
+ assert('is_array($filterSrc)');
+
+ $parsedFilters = array();
+
+ foreach ($filterSrc as $filter) {
+
+ if (is_string($filter)) {
+ $filter = array($filter);
+ }
+
+ if (!is_array($filter)) {
+ throw new Exception('Invalid authentication processing filter configuration: ' .
+ 'One of the filters wasn\'t a string or an array.');
+ }
+
+ $parsedFilters[] = self::parseFilter($filter);
+ }
+
+ return $parsedFilters;
+ }
+
+
+ /**
+ * Parse an authentication processing filter.
+ *
+ * @param array $config Array with the authentication processing filter configuration.
+ * @return SimpleSAML_Auth_ProcessingFilter The parsed filter.
+ */
+ private static function parseFilter($config) {
+ assert('is_array($config)');
+
+ if (!array_key_exists(0, $config)) {
+ throw new Exception('Authentication processing filter without name given.');
+ }
+
+ $className = SimpleSAML_Module::resolveClass($config[0], 'Auth_Process',
+ 'SimpleSAML_Auth_ProcessingFilter');
+
+ unset($config[0]);
+ return new $className($config, NULL);
+ }
+
+
+ /**
+ * Process the given state.
+ *
+ * This function will only return if processing completes. If processing requires showing
+ * a page to the user, we will redirect to the URL set in $state['ReturnURL'] after processing is
+ * completed.
+ *
+ * @param array &$state The state we are processing.
+ */
+ public function processState(&$state) {
+ assert('is_array($state)');
+ assert('array_key_exists("ReturnURL", $state)');
+
+ $state[self::FILTERS_INDEX] = $this->filters;
+
+ while (count($state[self::FILTERS_INDEX]) > 0) {
+ $filter = array_shift($state[self::FILTERS_INDEX]);
+ $filter->process($state);
+ }
+
+ /* Completed. */
+ }
+
+
+ /**
+ * Continues processing of the state.
+ *
+ * This function is used to resume processing by filters which for example needed to show
+ * a page to the user.
+ *
+ * This function will never return. In the case of an exception, exception handling should
+ * be left to the main simpleSAMLphp exception handler.
+ *
+ * @param array $state The state we are processing.
+ */
+ public static function resumeProcessing($state) {
+ assert('is_array($state)');
+
+ while (count($state[self::FILTERS_INDEX]) > 0) {
+ $filter = array_shift($state[self::FILTERS_INDEX]);
+ $filter->process($state);
+ }
+
+ assert('array_key_exists("ReturnURL", $state)');
+
+ /* Completed. Save state information, and redirect to the URL specified
+ * in $state['ReturnURL'].
+ */
+ $id = SimpleSAML_Auth_State::saveState($state, self::COMPLETED_STAGE);
+ SimpleSAML_Utilities::redirect($state['ReturnURL'], array(self::AUTHPARAM => $id));
+ }
+
+
+ /**
+ * Retrieve a state which has finished processing.
+ *
+ * @param string $id The identifier of the state. This can be found in the request parameter
+ * with index from SimpleSAML_Auth_ProcessingChain::AUTHPARAM.
+ */
+ public static function fetchProcessedState($id) {
+ assert('is_string($id)');
+
+ return SimpleSAML_Auth_State::loadState($id, self::COMPLETED_STAGE);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/lib/SimpleSAML/Auth/ProcessingFilter.php b/lib/SimpleSAML/Auth/ProcessingFilter.php
new file mode 100644
index 0000000..a9d42ac
--- /dev/null
+++ b/lib/SimpleSAML/Auth/ProcessingFilter.php
@@ -0,0 +1,69 @@
+<?php
+
+
+/**
+ * Base class for authentication processing filters.
+ *
+ * All authentication processing filters must support serialization.
+ *
+ * The current request is stored in an associative array. It has the following defined attributes:
+ * - 'Attributes' The attributes of the user.
+ * - 'Destination' Metadata of the destination (SP).
+ * - 'Source' Metadata of the source (IdP).
+ *
+ * It may also contain other attributes. If an authentication processing filter wishes to store other
+ * information in it, it should have a name on the form 'module:filter:attributename', to avoid name
+ * collisions.
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+abstract class SimpleSAML_Auth_ProcessingFilter {
+
+ /**
+ * Priority of this filter.
+ *
+ * Used when merging IdP and SP processing chains.
+ * The priority can be any integer. The default for most filters is 50. Filters may however
+ * specify their own default, if they typically should be amongst the first or the last filters.
+ *
+ * The prioroty can also be overridden by the user by specifying the '%priority' option.
+ */
+ public $priority = 50;
+
+
+ /**
+ * Constructor for a processing filter.
+ *
+ * Any processing filter which implements its own constructor must call this
+ * constructor first.
+ *
+ * @param array &$config Configuration for this filter.
+ * @param mixed $reserved For future use.
+ */
+ public function __construct(&$config, $reserved) {
+ assert('is_array($config)');
+
+ if(array_key_exists('%priority', $config)) {
+ $this->priority = $config['%priority'];
+ if(!is_int($this->priority)) {
+ throw new Exception('Invalid priority: ' . var_export($this->priority, TRUE));
+ }
+ unset($config['%priority']);
+ }
+ }
+
+
+ /**
+ * Process a request.
+ *
+ * When a filter returns from this function, it is assumed to have completed its task.
+ *
+ * @param array &$request The request we are currently processing.
+ */
+ abstract public function process(&$request);
+
+}
+
+?> \ No newline at end of file
diff --git a/modules/core/default-enable b/modules/core/default-enable
new file mode 100644
index 0000000..25615cb
--- /dev/null
+++ b/modules/core/default-enable
@@ -0,0 +1,3 @@
+This file indicates that the default state of this module
+is enabled. To disable, create a file named disable in the
+same directory as this file.
diff --git a/modules/core/lib/Auth/Process/AttributeAdd.php b/modules/core/lib/Auth/Process/AttributeAdd.php
new file mode 100644
index 0000000..5d31aca
--- /dev/null
+++ b/modules/core/lib/Auth/Process/AttributeAdd.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * Filter to add attributes.
+ *
+ * This filter allows you to add attributes to the attribute set being processed.
+ *
+ * Example - add attribute, single value:
+ * <code>
+ * 'authproc' => array(
+ * array('core:AttributeAdd', 'source' => 'myidp'),
+ * ),
+ * </code>
+ *
+ * Examle - add attribute, multiple values:
+ * <code>
+ * 'authproc' => array(
+ * array('core:AttributeAdd', 'groups' => array('users', 'members')),
+ * ),
+ * </code>
+ *
+ * Examle - replace attribute, single value:
+ * <code>
+ * 'authproc' => array(
+ * array('core:AttributeAdd', '%replace', 'uid' => array('guest')),
+ * ),
+ * </code>
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_core_Auth_Process_AttributeAdd extends SimpleSAML_Auth_ProcessingFilter {
+
+ /**
+ * Flag which indicates wheter this filter should append new values or replace old values.
+ */
+ private $replace = FALSE;
+
+
+ /**
+ * Attributes which should be added/appended.
+ *
+ * Assiciative array of arrays.
+ */
+ private $attributes = array();
+
+
+ /**
+ * Initialize this filter.
+ *
+ * @param array $config Configuration information about this filter.
+ * @param mixed $reserved For future use.
+ */
+ public function __construct($config, $reserved) {
+ parent::__construct($config, $reserved);
+
+ assert('is_array($config)');
+
+ foreach($config as $name => $values) {
+ if(is_int($name)) {
+ if($values === '%replace') {
+ $this->replace = TRUE;
+ } else {
+ throw new Exception('Unknown flag: ' . var_export($values, TRUE));
+ }
+ continue;
+ }
+
+ if(!is_string($name)) {
+ throw new Exception('Invalid attribute name: ' . var_export($name, TRUE));
+ }
+
+ if(!is_array($values)) {
+ $values = array($values);
+ }
+ foreach($values as $value) {
+ if(!is_string($value)) {
+ throw new Exception('Invalid value for attribute ' . $name . ': ' .
+ var_export($values, TRUE));
+ }
+ }
+
+ $this->attributes[$name] = $values;
+ }
+ }
+
+
+ /**
+ * Apply filter to add or replace attributes.
+ *
+ * Add or replace existing attributes with the configured values.
+ *
+ * @param array &$request The current request
+ */
+ public function process(&$request) {
+ assert('is_array($request)');
+ assert('array_key_exists("Attributes", $request)');
+
+ $attributes =& $request['Attributes'];
+
+ foreach($this->attributes as $name => $values) {
+ if($this->replace === TRUE || !array_key_exists($name, $attributes)) {
+ $attributes[$name] = $values;
+ } else {
+ $attributes[$name] = array_merge($attributes[$name], $values);
+ }
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/modules/core/lib/Auth/Process/AttributeLimit.php b/modules/core/lib/Auth/Process/AttributeLimit.php
new file mode 100644
index 0000000..d96df12
--- /dev/null
+++ b/modules/core/lib/Auth/Process/AttributeLimit.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * A filter for limiting which attributes are passed on.
+ *
+ * Example - remove all attributes except 'cn' and 'mail':
+ * <code>
+ * 'authproc' => array(
+ * array('core:AttributeLimit', 'cn', 'mail'),
+ * ),
+ * </code>
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_core_Auth_Process_AttributeLimit extends SimpleSAML_Auth_ProcessingFilter {
+
+ /**
+ * List of attributes which this filter will allow through.
+ */
+ private $allowedAttributes = array();
+
+
+ /**
+ * Initialize this filter.
+ *
+ * @param array $config Configuration information about this filter.
+ * @param mixed $reserved For future use
+ */
+ public function __construct($config, $reserved) {
+ parent::__construct($config, $reserved);
+
+ assert('is_array($config)');
+
+ foreach($config as $name) {
+
+ if(!is_string($name)) {
+ throw new Exception('Invalid attribute name: ' . var_export($name, TRUE));
+ }
+
+ $this->allowedAttributes[] = $name;
+ }
+ }
+
+
+ /**
+ * Apply filter to remove attributes.
+ *
+ * Removes all attributes which aren't one of the allowed attributes.
+ *
+ * @param array &$request The current request
+ */
+ public function process(&$request) {
+ assert('is_array($request)');
+ assert('array_key_exists("Attributes", $request)');
+
+ $attributes =& $request['Attributes'];
+
+ foreach($attributes as $name => $values) {
+ if(!in_array($name, $this->allowedAttributes, TRUE)) {
+ unset($attributes[$name]);
+ }
+ }
+
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/modules/core/lib/Auth/Process/AttributeMap.php b/modules/core/lib/Auth/Process/AttributeMap.php
new file mode 100644
index 0000000..9631b0b
--- /dev/null
+++ b/modules/core/lib/Auth/Process/AttributeMap.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * Attribute filter for renaming attributes.
+ *
+ * Example 1 - apply map stored in attributemap/defaultmap.php:
+ * <code>
+ * 'authproc' => array(
+ * array('core:AttributeMap', 'defaultmaps'),
+ * ),
+ * </code>
+ *
+ * Example 2 - rename attributes 'mail' and 'uid' to 'email' and 'user':
+ * <code>
+ * 'authproc' => array(
+ * array('core:AttributeMap', 'mail' => 'email', 'uid' => 'user'),
+ * ),
+ * </code>
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_core_Auth_Process_AttributeMap extends SimpleSAML_Auth_ProcessingFilter {
+
+ /**
+ * Assosiative array with the mappings of attribute names.
+ */
+ private $map = array();
+
+
+ /**
+ * Initialize this filter, parse configuration
+ *
+ * @param array $config Configuration information about this filter.
+ * @param mixed $reserved For future use.
+ */
+ public function __construct($config, $reserved) {
+ parent::__construct($config, $reserved);
+
+ assert('is_array($config)');
+
+ foreach($config as $origName => $newName) {
+ if(is_int($origName)) {
+ /* No index given - this is a map file. */
+ $this->loadMapFile($newName);
+ continue;
+ }
+
+ if(!is_string($origName)) {
+ throw new Exception('Invalid attribute name: ' . var_export($origName, TRUE));
+ }
+
+ if(!is_string($newName)) {
+ throw new Exception('Invalid attribute name: ' . var_export($newName, TRUE));
+ }
+
+ $this->map[$origName] = $newName;
+ }
+ }
+
+
+ /**
+ * Loads and merges in a file with a attribute map.
+ *
+ * @param string $fileName Name of attribute map file. Expected to be in the attributenamemapdir.
+ */
+ private function loadMapFile($fileName) {
+ $config = SimpleSAML_Configuration::getInstance();
+ $filePath = $config->getPathValue('attributenamemapdir') . $fileName . '.php';
+
+ if(!file_exists($filePath)) {
+ throw new Exception('Could not find attributemap file: ' . $filePath);
+ }
+
+ $attributemap = NULL;
+ include($filePath);
+ if(!is_array($attributemap)) {
+ throw new Exception('Attribute map file "' . $filePath . '" didn\'t define an attribute map.');
+ }
+
+ $this->map = array_merge($this->map, $attributemap);
+ }
+
+
+ /**
+ * Apply filter to rename attributes.
+ *
+ * @param array &$request The current request
+ */
+ public function process(&$request) {
+ assert('is_array($request');
+ assert('array_key_exists("Attributes", $request)');
+
+ $attributes =& $request['Attributes'];
+
+ foreach($attributes as $name => $values) {
+ if(array_key_exists($name, $this->map)) {
+ $attributes[$this->map[$name]] = $values;
+ unset($attributes[$name]);
+ }
+ }
+
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/modules/exampleauth/lib/Auth/Process/RedirectTest.php b/modules/exampleauth/lib/Auth/Process/RedirectTest.php
new file mode 100644
index 0000000..02a4220
--- /dev/null
+++ b/modules/exampleauth/lib/Auth/Process/RedirectTest.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * A simple processing filter for testing that redirection works as it should.
+ *
+ */
+class sspmod_exampleauth_Auth_Process_RedirectTest extends SimpleSAML_Auth_ProcessingFilter {
+
+
+ /**
+ * Initialize processing of the redirect test.
+ *
+ * @param array &$state The state we should update.
+ */
+ public function process(&$state) {
+ assert('is_array($state)');
+ assert('array_key_exists("Attributes", $state)');
+
+ /* To check whether the state is saved correctly. */
+ $state['Attributes']['RedirectTest1'] = array('OK');
+
+ /* Save state and redirect. */
+ $id = SimpleSAML_Auth_State::saveState($state, 'exampleauth:redirectfilter-test');
+ $url = SimpleSAML_Module::getModuleURL('exampleauth/redirecttest.php');
+ SimpleSAML_Utilities::redirect($url, array('StateId' => $id));
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/modules/exampleauth/www/redirecttest.php b/modules/exampleauth/www/redirecttest.php
new file mode 100644
index 0000000..39a1b54
--- /dev/null
+++ b/modules/exampleauth/www/redirecttest.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * Request handler for redirect filter test.
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+
+if (!array_key_exists('StateId', $_REQUEST)) {
+ throw new SimpleSAML_Error_BadRequest('Missing required StateId query parameter.');
+}
+
+$id = $_REQUEST['StateId'];
+$state = SimpleSAML_Auth_State::loadState($id, 'exampleauth:redirectfilter-test');
+
+$state['Attributes']['RedirectTest2'] = array('OK');
+
+SimpleSAML_Auth_ProcessingChain::resumeProcessing($state);
+
+?> \ No newline at end of file
diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php
index 55d53a0..b71d187 100644
--- a/www/saml2/idp/SSOService.php
+++ b/www/saml2/idp/SSOService.php
@@ -139,6 +139,13 @@ if (isset($_GET['SAMLRequest'])) {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'CACHEAUTHNREQUEST', $exception);
}
+} elseif(isset($_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM])) {
+
+ /* Resume from authentication processing chain. */
+ $authProcId = $_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM];
+ $authProcState = SimpleSAML_Auth_ProcessingChain::fetchProcessedState($authProcId);
+ $requestcache = $authProcState['core:saml20-idp:requestcache'];
+
} else {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SSOSERVICEPARAMS');
}
@@ -270,6 +277,34 @@ if($needAuth && !$isPassive) {
$filteredattributes = $afilter->getAttributes();
+
+ /* Authentication processing operations. */
+ if (array_key_exists('AuthProcState', $requestcache)) {
+ /* Processed earlier, saved in requestcache. */
+ $authProcState = $requestcache['AuthProcState'];
+
+ } elseif (isset($authProcState)) {
+ /* Returned from redirect during processing. */
+ $requestcache['AuthProcState'] = $authProcState;
+
+ } else {
+ /* Not processed. */
+ $pc = new SimpleSAML_Auth_ProcessingChain($idpmetadata, $spmetadata);
+
+ $authProcState = array(
+ 'core:saml20-idp:requestcache' => $requestcache,
+ 'ReturnURL' => SimpleSAML_Utilities::selfURLNoQuery(),
+ 'Attributes' => $filteredattributes,
+ 'Destination' => $spmetadata,
+ 'Source' => $idpmetadata,
+ );
+
+ $pc->processState($authProcState);
+
+ $requestcache['AuthProcState'] = $authProcState;
+ }
+
+ $filteredattributes = $authProcState['Attributes'];
diff --git a/www/shib13/idp/SSOService.php b/www/shib13/idp/SSOService.php
index 495f20d..0aecf9c 100644
--- a/www/shib13/idp/SSOService.php
+++ b/www/shib13/idp/SSOService.php
@@ -91,6 +91,12 @@ if (isset($_GET['shire'])) {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'CACHEAUTHNREQUEST', $exception);
}
+} elseif(isset($_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM])) {
+
+ /* Resume from authentication processing chain. */
+ $authProcId = $_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM];
+ $authProcState = SimpleSAML_Auth_ProcessingChain::fetchProcessedState($authProcId);
+ $requestcache = $authProcState['core:shib13-idp:requestcache'];
} else {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SSOSERVICEPARAMS');
@@ -184,6 +190,35 @@ if (!$session->isAuthenticated($authority) ) {
$filteredattributes = $afilter->getAttributes();
+
+ /* Authentication processing operations. */
+ if (array_key_exists('AuthProcState', $requestcache)) {
+ /* Processed earlier, saved in requestcache. */
+ $authProcState = $requestcache['AuthProcState'];
+
+ } elseif (isset($authProcState)) {
+ /* Returned from redirect during processing. */
+ $requestcache['AuthProcState'] = $authProcState;
+
+ } else {
+ /* Not processed. */
+ $pc = new SimpleSAML_Auth_ProcessingChain($idpmetadata, $spmetadata);
+
+ $authProcState = array(
+ 'core:shib13-idp:requestcache' => $requestcache,
+ 'ReturnURL' => SimpleSAML_Utilities::selfURLNoQuery(),
+ 'Attributes' => $filteredattributes,
+ 'Destination' => $spmetadata,
+ 'Source' => $idpmetadata,
+ );
+
+ $pc->processState($authProcState);
+
+ $requestcache['AuthProcState'] = $authProcState;
+ }
+
+ $filteredattributes = $authProcState['Attributes'];
+
/*
* Dealing with attribute release consent.