ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
ProcessingChain.php
Go to the documentation of this file.
1<?php
2
14{
15
16
20 const FILTERS_INDEX = 'SimpleSAML_Auth_ProcessingChain.filters';
21
22
26 const COMPLETED_STAGE = 'SimpleSAML_Auth_ProcessingChain.completed';
27
28
33 const AUTHPARAM = 'AuthProcId';
34
35
39 private $filters;
40
41
49 public function __construct($idpMetadata, $spMetadata, $mode = 'idp')
50 {
51 assert(is_array($idpMetadata));
52 assert(is_array($spMetadata));
53
54 $this->filters = array();
55
57 $configauthproc = $config->getArray('authproc.' . $mode, null);
58
59 if (!empty($configauthproc)) {
60 $configfilters = self::parseFilterList($configauthproc);
61 self::addFilters($this->filters, $configfilters);
62 }
63
64 if (array_key_exists('authproc', $idpMetadata)) {
65 $idpFilters = self::parseFilterList($idpMetadata['authproc']);
66 self::addFilters($this->filters, $idpFilters);
67 }
68
69 if (array_key_exists('authproc', $spMetadata)) {
70 $spFilters = self::parseFilterList($spMetadata['authproc']);
71 self::addFilters($this->filters, $spFilters);
72 }
73
74
75 SimpleSAML\Logger::debug('Filter config for ' . $idpMetadata['entityid'] . '->' .
76 $spMetadata['entityid'] . ': ' . str_replace("\n", '', var_export($this->filters, true)));
77 }
78
79
88 private static function addFilters(&$target, $src)
89 {
90 assert(is_array($target));
91 assert(is_array($src));
92
93 foreach ($src as $filter) {
94 $fp = $filter->priority;
95
96 // Find insertion position for filter
97 for ($i = count($target)-1; $i >= 0; $i--) {
98 if ($target[$i]->priority <= $fp) {
99 // The new filter should be inserted after this one
100 break;
101 }
102 }
103 /* $i now points to the filter which should preceede the current filter. */
104 array_splice($target, $i+1, 0, array($filter));
105 }
106 }
107
108
115 private static function parseFilterList($filterSrc)
116 {
117 assert(is_array($filterSrc));
118
119 $parsedFilters = array();
120
121 foreach ($filterSrc as $priority => $filter) {
122 if (is_string($filter)) {
123 $filter = array('class' => $filter);
124 }
125
126 if (!is_array($filter)) {
127 throw new Exception('Invalid authentication processing filter configuration: ' .
128 'One of the filters wasn\'t a string or an array.');
129 }
130
131 $parsedFilters[] = self::parseFilter($filter, $priority);
132 }
133
134 return $parsedFilters;
135 }
136
137
146 private static function parseFilter($config, $priority)
147 {
148 assert(is_array($config));
149
150 if (!array_key_exists('class', $config)) {
151 throw new Exception('Authentication processing filter without name given.');
152 }
153
154 $className = SimpleSAML\Module::resolveClass($config['class'], 'Auth_Process', 'SimpleSAML_Auth_ProcessingFilter');
155 $config['%priority'] = $priority;
156 unset($config['class']);
157 return new $className($config, null);
158 }
159
160
181 public function processState(&$state)
182 {
183 assert(is_array($state));
184 assert(array_key_exists('ReturnURL', $state) || array_key_exists('ReturnCall', $state));
185 assert(!array_key_exists('ReturnURL', $state) || !array_key_exists('ReturnCall', $state));
186
188
189 try {
190 // TODO: remove this in SSP 2.0
191 if (!array_key_exists('UserID', $state)) {
192 // No unique user ID present. Attempt to add one.
194 }
195
196 while (count($state[self::FILTERS_INDEX]) > 0) {
197 $filter = array_shift($state[self::FILTERS_INDEX]);
198 $filter->process($state);
199 }
200 } catch (SimpleSAML_Error_Exception $e) {
201 // No need to convert the exception
202 throw $e;
203 } catch (Exception $e) {
204 /*
205 * To be consistent with the exception we return after an redirect,
206 * we convert this exception before returning it.
207 */
209 }
210
211 // Completed
212 }
213
214
226 public static function resumeProcessing($state)
227 {
228 assert(is_array($state));
229
230 while (count($state[self::FILTERS_INDEX]) > 0) {
231 $filter = array_shift($state[self::FILTERS_INDEX]);
232 try {
233 $filter->process($state);
234 } catch (SimpleSAML_Error_Exception $e) {
236 } catch (Exception $e) {
239 }
240 }
241
242 // Completed
243
244 assert(array_key_exists('ReturnURL', $state) || array_key_exists('ReturnCall', $state));
245 assert(!array_key_exists('ReturnURL', $state) || !array_key_exists('ReturnCall', $state));
246
247
248 if (array_key_exists('ReturnURL', $state)) {
249 /*
250 * Save state information, and redirect to the URL specified
251 * in $state['ReturnURL'].
252 */
253 $id = SimpleSAML_Auth_State::saveState($state, self::COMPLETED_STAGE);
254 \SimpleSAML\Utils\HTTP::redirectTrustedURL($state['ReturnURL'], array(self::AUTHPARAM => $id));
255 } else {
256 /* Pass the state to the function defined in $state['ReturnCall']. */
257
258 // We are done with the state array in the session. Delete it.
260
261 $func = $state['ReturnCall'];
262 assert(is_callable($func));
263
264 call_user_func($func, $state);
265 assert(false);
266 }
267 }
268
269
280 public function processStatePassive(&$state)
281 {
282 assert(is_array($state));
283 // Should not be set when calling this method
284 assert(!array_key_exists('ReturnURL', $state));
285
286 // Notify filters about passive request
287 $state['isPassive'] = true;
288
290
291 // TODO: remove this in SSP 2.0
292 if (!array_key_exists('UserID', $state)) {
293 // No unique user ID present. Attempt to add one.
295 }
296
297 while (count($state[self::FILTERS_INDEX]) > 0) {
298 $filter = array_shift($state[self::FILTERS_INDEX]);
299 try {
300 $filter->process($state);
301 // Ignore SimpleSAML_Error_NoPassive exceptions
302 } catch (SimpleSAML_Error_NoPassive $e) {
303 // @deprecated will be removed in 2.0
304 // Ignore \SimpleSAML\Error\NoPassive exceptions
305 } catch (\SimpleSAML\Module\saml\Error\NoPassive $e) {
306 // Ignore \SimpleSAML\Module\saml\Error\NoPassive exceptions
307 }
308 }
309 }
310
318 public static function fetchProcessedState($id)
319 {
320 assert(is_string($id));
321
322 return SimpleSAML_Auth_State::loadState($id, self::COMPLETED_STAGE);
323 }
324
325
329 private static function addUserID(&$state)
330 {
331 assert(is_array($state));
332 assert(array_key_exists('Attributes', $state));
333
334 if (isset($state['Destination']['userid.attribute'])) {
335 $attributeName = $state['Destination']['userid.attribute'];
336 SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated.");
337 } elseif (isset($state['Source']['userid.attribute'])) {
338 $attributeName = $state['Source']['userid.attribute'];
339 SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated.");
340 } else {
341 // Default attribute
342 $attributeName = 'eduPersonPrincipalName';
343 }
344
345 if (!array_key_exists($attributeName, $state['Attributes'])) {
346 return;
347 }
348
349 $uid = $state['Attributes'][$attributeName];
350 if (count($uid) === 0) {
351 SimpleSAML\Logger::warning('Empty user id attribute [' . $attributeName . '].');
352 return;
353 }
354
355 if (count($uid) > 1) {
356 SimpleSAML\Logger::warning('Multiple attribute values for user id attribute [' . $attributeName . '].');
357 return;
358 }
359
360 // TODO: the attribute value should be trimmed
361 $uid = $uid[0];
362
363 if (empty($uid)) {
364 SimpleSAML\Logger::warning('Empty value in attribute '.$attributeName.". on user. Cannot set UserID.");
365 return;
366 }
367 $state['UserID'] = $uid;
368 }
369}
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
An exception for terminatinating execution or to throw for unit testing.
static warning($string)
Definition: Logger.php:177
static debug($string)
Definition: Logger.php:211
static resolveClass($id, $type, $subclass=null)
Resolve module class.
Definition: Module.php:169
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
Definition: HTTP.php:959
const AUTHPARAM
The request parameter we will use to pass the state identifier when we redirect after having complete...
processState(&$state)
Process the given state.
static addFilters(&$target, $src)
Sort & merge filter configuration.
processStatePassive(&$state)
Process the given state passivly.
static parseFilterList($filterSrc)
Parse an array of authentication processing filters.
__construct($idpMetadata, $spMetadata, $mode='idp')
Initialize an authentication processing chain for the given service provider and identity provider.
const FILTERS_INDEX
The list of remaining filters which should be applied to the state.
static parseFilter($config, $priority)
Parse an authentication processing filter.
static fetchProcessedState($id)
Retrieve a state which has finished processing.
$filters
All authentication processing filters, in the order they should be applied.
const COMPLETED_STAGE
The stage we use for completed requests.
static resumeProcessing($state)
Continues processing of the state.
static deleteState(&$state)
Delete state.
Definition: State.php:319
static throwException($state, SimpleSAML_Error_Exception $exception)
Throw exception to the state exception handler.
Definition: State.php:343
static saveState(&$state, $stage, $rawId=false)
Save the state.
Definition: State.php:194
static loadState($id, $stage, $allowMissing=false)
Retrieve saved state.
Definition: State.php:259
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.
Class SimpleSAML_Error_NoPassive.
Definition: NoPassive.php:13
$i
Definition: disco.tpl.php:19
if(!array_key_exists('StateId', $_REQUEST)) $id
$config
Definition: bootstrap.php:15
$idpMetadata
$spMetadata
$target
Definition: test.php:19
Attribute-related utility methods.