ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
ProcessingChain.php
Go to the documentation of this file.
1<?php
2
14
15
19 const FILTERS_INDEX = 'SimpleSAML_Auth_ProcessingChain.filters';
20
21
25 const COMPLETED_STAGE = 'SimpleSAML_Auth_ProcessingChain.completed';
26
27
32 const AUTHPARAM = 'AuthProcId';
33
34
38 private $filters;
39
40
48 public function __construct($idpMetadata, $spMetadata, $mode = 'idp') {
49 assert('is_array($idpMetadata)');
50 assert('is_array($spMetadata)');
51
52 $this->filters = array();
53
55 $configauthproc = $config->getArray('authproc.' . $mode, NULL);
56
57 if (!empty($configauthproc)) {
58 $configfilters = self::parseFilterList($configauthproc);
59 self::addFilters($this->filters, $configfilters);
60 }
61
62 if (array_key_exists('authproc', $idpMetadata)) {
63 $idpFilters = self::parseFilterList($idpMetadata['authproc']);
64 self::addFilters($this->filters, $idpFilters);
65 }
66
67 if (array_key_exists('authproc', $spMetadata)) {
68 $spFilters = self::parseFilterList($spMetadata['authproc']);
69 self::addFilters($this->filters, $spFilters);
70 }
71
72
73 SimpleSAML\Logger::debug('Filter config for ' . $idpMetadata['entityid'] . '->' .
74 $spMetadata['entityid'] . ': ' . str_replace("\n", '', var_export($this->filters, TRUE)));
75
76 }
77
78
87 private static function addFilters(&$target, $src) {
88 assert('is_array($target)');
89 assert('is_array($src)');
90
91 foreach ($src as $filter) {
92 $fp = $filter->priority;
93
94 // Find insertion position for filter
95 for($i = count($target)-1; $i >= 0; $i--) {
96 if ($target[$i]->priority <= $fp) {
97 // The new filter should be inserted after this one
98 break;
99 }
100 }
101 /* $i now points to the filter which should preceede the current filter. */
102 array_splice($target, $i+1, 0, array($filter));
103 }
104
105 }
106
107
114 private static function parseFilterList($filterSrc) {
115 assert('is_array($filterSrc)');
116
117 $parsedFilters = array();
118
119 foreach ($filterSrc as $priority => $filter) {
120
121 if (is_string($filter)) {
122 $filter = array('class' => $filter);
123 }
124
125 if (!is_array($filter)) {
126 throw new Exception('Invalid authentication processing filter configuration: ' .
127 'One of the filters wasn\'t a string or an array.');
128 }
129
130 $parsedFilters[] = self::parseFilter($filter, $priority);
131 }
132
133 return $parsedFilters;
134 }
135
136
145 private static function parseFilter($config, $priority) {
146 assert('is_array($config)');
147
148 if (!array_key_exists('class', $config))
149 throw new Exception('Authentication processing filter without name given.');
150
151 $className = SimpleSAML\Module::resolveClass($config['class'], 'Auth_Process', 'SimpleSAML_Auth_ProcessingFilter');
152 $config['%priority'] = $priority;
153 unset($config['class']);
154 return new $className($config, NULL);
155 }
156
157
178 public function processState(&$state) {
179 assert('is_array($state)');
180 assert('array_key_exists("ReturnURL", $state) || array_key_exists("ReturnCall", $state)');
181 assert('!array_key_exists("ReturnURL", $state) || !array_key_exists("ReturnCall", $state)');
182
184
185 try {
186
187 // TODO: remove this in SSP 2.0
188 if (!array_key_exists('UserID', $state)) {
189 // No unique user ID present. Attempt to add one.
191 }
192
193 while (count($state[self::FILTERS_INDEX]) > 0) {
194 $filter = array_shift($state[self::FILTERS_INDEX]);
195 $filter->process($state);
196 }
197
198 } catch (SimpleSAML_Error_Exception $e) {
199 // No need to convert the exception
200 throw $e;
201 } catch (Exception $e) {
202 /*
203 * To be consistent with the exception we return after an redirect,
204 * we convert this exception before returning it.
205 */
207 }
208
209 // Completed
210 }
211
212
224 public static function resumeProcessing($state) {
225 assert('is_array($state)');
226
227 while (count($state[self::FILTERS_INDEX]) > 0) {
228 $filter = array_shift($state[self::FILTERS_INDEX]);
229 try {
230 $filter->process($state);
231 } catch (SimpleSAML_Error_Exception $e) {
233 } catch (Exception $e) {
236 }
237 }
238
239 // Completed
240
241 assert('array_key_exists("ReturnURL", $state) || array_key_exists("ReturnCall", $state)');
242 assert('!array_key_exists("ReturnURL", $state) || !array_key_exists("ReturnCall", $state)');
243
244
245 if (array_key_exists('ReturnURL', $state)) {
246 /*
247 * Save state information, and redirect to the URL specified
248 * in $state['ReturnURL'].
249 */
250 $id = SimpleSAML_Auth_State::saveState($state, self::COMPLETED_STAGE);
251 \SimpleSAML\Utils\HTTP::redirectTrustedURL($state['ReturnURL'], array(self::AUTHPARAM => $id));
252 } else {
253 /* Pass the state to the function defined in $state['ReturnCall']. */
254
255 // We are done with the state array in the session. Delete it.
257
258 $func = $state['ReturnCall'];
259 assert('is_callable($func)');
260
261 call_user_func($func, $state);
262 assert(FALSE);
263 }
264 }
265
266
277 public function processStatePassive(&$state) {
278 assert('is_array($state)');
279 // Should not be set when calling this method
280 assert('!array_key_exists("ReturnURL", $state)');
281
282 // Notify filters about passive request
283 $state['isPassive'] = TRUE;
284
286
287 // TODO: remove this in SSP 2.0
288 if (!array_key_exists('UserID', $state)) {
289 // No unique user ID present. Attempt to add one.
291 }
292
293 while (count($state[self::FILTERS_INDEX]) > 0) {
294 $filter = array_shift($state[self::FILTERS_INDEX]);
295 try {
296 $filter->process($state);
297
298 // Ignore SimpleSAML_Error_NoPassive exceptions
299 } catch (SimpleSAML_Error_NoPassive $e) { }
300 }
301 }
302
310 public static function fetchProcessedState($id) {
311 assert('is_string($id)');
312
313 return SimpleSAML_Auth_State::loadState($id, self::COMPLETED_STAGE);
314 }
315
316
320 private static function addUserID(&$state) {
321 assert('is_array($state)');
322 assert('array_key_exists("Attributes", $state)');
323
324 if (isset($state['Destination']['userid.attribute'])) {
325 $attributeName = $state['Destination']['userid.attribute'];
326 SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated.");
327 } elseif (isset($state['Source']['userid.attribute'])) {
328 $attributeName = $state['Source']['userid.attribute'];
329 SimpleSAML\Logger::warning("The 'userid.attribute' option has been deprecated.");
330 } else {
331 // Default attribute
332 $attributeName = 'eduPersonPrincipalName';
333 }
334
335 if (!array_key_exists($attributeName, $state['Attributes'])) {
336 return;
337 }
338
339 $uid = $state['Attributes'][$attributeName];
340 if (count($uid) === 0) {
341 SimpleSAML\Logger::warning('Empty user id attribute [' . $attributeName . '].');
342 return;
343 }
344
345 if (count($uid) > 1) {
346 SimpleSAML\Logger::warning('Multiple attribute values for user id attribute [' . $attributeName . '].');
347 return;
348 }
349
350 // TODO: the attribute value should be trimmed
351 $uid = $uid[0];
352
353 if (empty($uid)) {
354 SimpleSAML\Logger::warning('Empty value in attribute '.$attributeName.". on user. Cannot set UserID.");
355 return;
356 }
357 $state['UserID'] = $uid;
358 }
359
360}
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:179
static debug($string)
Definition: Logger.php:213
static resolveClass($id, $type, $subclass=null)
Resolve module class.
Definition: Module.php:252
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
Definition: HTTP.php:962
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.
$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:12
$i
Definition: disco.tpl.php:19
if(!array_key_exists('StateId', $_REQUEST)) $id
$idpMetadata
$spMetadata