ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
IdP.php
Go to the documentation of this file.
1<?php
2
3
12{
13
19 private static $idpCache = array();
20
21
27 private $id;
28
29
39
40
46 private $config;
47
48
54 private $authSource;
55
56
64 private function __construct($id)
65 {
66 assert('is_string($id)');
67
68 $this->id = $id;
69
72
73 if (substr($id, 0, 6) === 'saml2:') {
74 if (!$globalConfig->getBoolean('enable.saml20-idp', false)) {
75 throw new SimpleSAML_Error_Exception('enable.saml20-idp disabled in config.php.');
76 }
77 $this->config = $metadata->getMetaDataConfig(substr($id, 6), 'saml20-idp-hosted');
78 } elseif (substr($id, 0, 6) === 'saml1:') {
79 if (!$globalConfig->getBoolean('enable.shib13-idp', false)) {
80 throw new SimpleSAML_Error_Exception('enable.shib13-idp disabled in config.php.');
81 }
82 $this->config = $metadata->getMetaDataConfig(substr($id, 6), 'shib13-idp-hosted');
83 } elseif (substr($id, 0, 5) === 'adfs:') {
84 if (!$globalConfig->getBoolean('enable.adfs-idp', false)) {
85 throw new SimpleSAML_Error_Exception('enable.adfs-idp disabled in config.php.');
86 }
87 $this->config = $metadata->getMetaDataConfig(substr($id, 5), 'adfs-idp-hosted');
88
89 try {
90 // this makes the ADFS IdP use the same SP associations as the SAML 2.0 IdP
91 $saml2EntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted');
92 $this->associationGroup = 'saml2:'.$saml2EntityId;
93 } catch (Exception $e) {
94 // probably no SAML 2 IdP configured for this host. Ignore the error
95 }
96 } else {
97 assert(false);
98 }
99
100 if ($this->associationGroup === null) {
101 $this->associationGroup = $this->id;
102 }
103
104 $auth = $this->config->getString('auth');
106 $this->authSource = new \SimpleSAML\Auth\Simple($auth);
107 } else {
108 throw new SimpleSAML_Error_Exception('No such "'.$auth.'" auth source found.');
109 }
110 }
111
112
118 public function getId()
119 {
120 return $this->id;
121 }
122
123
131 public static function getById($id)
132 {
133 assert('is_string($id)');
134
135 if (isset(self::$idpCache[$id])) {
136 return self::$idpCache[$id];
137 }
138
139 $idp = new self($id);
140 self::$idpCache[$id] = $idp;
141 return $idp;
142 }
143
144
152 public static function getByState(array &$state)
153 {
154 assert('isset($state["core:IdP"])');
155
156 return self::getById($state['core:IdP']);
157 }
158
159
165 public function getConfig()
166 {
167 return $this->config;
168 }
169
170
178 public function getSPName($assocId)
179 {
180 assert('is_string($assocId)');
181
182 $prefix = substr($assocId, 0, 4);
183 $spEntityId = substr($assocId, strlen($prefix) + 1);
185
186 if ($prefix === 'saml') {
187 try {
188 $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
189 } catch (Exception $e) {
190 try {
191 $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'shib13-sp-remote');
192 } catch (Exception $e) {
193 return null;
194 }
195 }
196 } else {
197 if ($prefix === 'adfs') {
198 $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'adfs-sp-remote');
199 } else {
200 return null;
201 }
202 }
203
204 if ($spMetadata->hasValue('name')) {
205 return $spMetadata->getLocalizedString('name');
206 } elseif ($spMetadata->hasValue('OrganizationDisplayName')) {
207 return $spMetadata->getLocalizedString('OrganizationDisplayName');
208 } else {
209 return array('en' => $spEntityId);
210 }
211 }
212
213
219 public function addAssociation(array $association)
220 {
221 assert('isset($association["id"])');
222 assert('isset($association["Handler"])');
223
224 $association['core:IdP'] = $this->id;
225
227 $session->addAssociation($this->associationGroup, $association);
228 }
229
230
236 public function getAssociations()
237 {
239 return $session->getAssociations($this->associationGroup);
240 }
241
242
249 {
250 assert('is_string($assocId)');
251
253 $session->terminateAssociation($this->associationGroup, $assocId);
254 }
255
256
262 public function isAuthenticated()
263 {
264 return $this->authSource->isAuthenticated();
265 }
266
267
273 public static function postAuthProc(array $state)
274 {
275 assert('is_callable($state["Responder"])');
276
277 if (isset($state['core:SP'])) {
279 $session->setData(
280 'core:idp-ssotime',
281 $state['core:IdP'].';'.$state['core:SP'],
282 time(),
284 );
285 }
286
287 call_user_func($state['Responder'], $state);
288 assert('FALSE');
289 }
290
291
299 public static function postAuth(array $state)
300 {
302
303 if (!$idp->isAuthenticated()) {
304 throw new SimpleSAML_Error_Exception('Not authenticated.');
305 }
306
307 $state['Attributes'] = $idp->authSource->getAttributes();
308
309 if (isset($state['SPMetadata'])) {
310 $spMetadata = $state['SPMetadata'];
311 } else {
312 $spMetadata = array();
313 }
314
315 if (isset($state['core:SP'])) {
317 $previousSSOTime = $session->getData('core:idp-ssotime', $state['core:IdP'].';'.$state['core:SP']);
318 if ($previousSSOTime !== null) {
319 $state['PreviousSSOTimestamp'] = $previousSSOTime;
320 }
321 }
322
323 $idpMetadata = $idp->getConfig()->toArray();
324
326
327 $state['ReturnCall'] = array('SimpleSAML_IdP', 'postAuthProc');
328 $state['Destination'] = $spMetadata;
329 $state['Source'] = $idpMetadata;
330
331 $pc->processState($state);
332
334 }
335
336
346 private function authenticate(array &$state)
347 {
348 if (isset($state['isPassive']) && (bool) $state['isPassive']) {
349 throw new SimpleSAML_Error_NoPassive('Passive authentication not supported.');
350 }
351
352 $this->authSource->login($state);
353 }
354
355
368 private function reauthenticate(array &$state)
369 {
370 $sourceImpl = $this->authSource->getAuthSource();
371 if ($sourceImpl === null) {
372 throw new SimpleSAML_Error_Exception('No such auth source defined.');
373 }
374
375 $sourceImpl->reauthenticate($state);
376 }
377
378
384 public function handleAuthenticationRequest(array &$state)
385 {
386 assert('isset($state["Responder"])');
387
388 $state['core:IdP'] = $this->id;
389
390 if (isset($state['SPMetadata']['entityid'])) {
391 $spEntityId = $state['SPMetadata']['entityid'];
392 } elseif (isset($state['SPMetadata']['entityID'])) {
393 $spEntityId = $state['SPMetadata']['entityID'];
394 } else {
395 $spEntityId = null;
396 }
397 $state['core:SP'] = $spEntityId;
398
399 // first, check whether we need to authenticate the user
400 if (isset($state['ForceAuthn']) && (bool) $state['ForceAuthn']) {
401 // force authentication is in effect
402 $needAuth = true;
403 } else {
404 $needAuth = !$this->isAuthenticated();
405 }
406
407 $state['IdPMetadata'] = $this->getConfig()->toArray();
408 $state['ReturnCallback'] = array('SimpleSAML_IdP', 'postAuth');
409
410 try {
411 if ($needAuth) {
412 $this->authenticate($state);
413 assert('FALSE');
414 } else {
415 $this->reauthenticate($state);
416 }
417 $this->postAuth($state);
418 } catch (SimpleSAML_Error_Exception $e) {
420 } catch (Exception $e) {
423 }
424 }
425
426
434 public function getLogoutHandler()
435 {
436 // find the logout handler
437 $logouttype = $this->getConfig()->getString('logouttype', 'traditional');
438 switch ($logouttype) {
439 case 'traditional':
440 $handler = 'SimpleSAML\IdP\TraditionalLogoutHandler';
441 break;
442 case 'iframe':
443 $handler = 'SimpleSAML\IdP\IFrameLogoutHandler';
444 break;
445 default:
446 throw new SimpleSAML_Error_Exception('Unknown logout handler: '.var_export($logouttype, true));
447 }
448
449 return new $handler($this);
450 }
451
452
460 public function finishLogout(array &$state)
461 {
462 assert('isset($state["Responder"])');
463
465 call_user_func($state['Responder'], $idp, $state);
466 assert('false');
467 }
468
469
479 public function handleLogoutRequest(array &$state, $assocId)
480 {
481 assert('isset($state["Responder"])');
482 assert('is_string($assocId) || is_null($assocId)');
483
484 $state['core:IdP'] = $this->id;
485 $state['core:TerminatedAssocId'] = $assocId;
486
487 if ($assocId !== null) {
490 $session->deleteData('core:idp-ssotime', $this->id.':'.$state['saml:SPEntityId']);
491 }
492
493 // terminate the local session
494 $id = SimpleSAML_Auth_State::saveState($state, 'core:Logout:afterbridge');
495 $returnTo = SimpleSAML\Module::getModuleURL('core/idp/resumelogout.php', array('id' => $id));
496
497 $this->authSource->logout($returnTo);
498
499 $handler = $this->getLogoutHandler();
500 $handler->startLogout($state, $assocId);
501 assert('false');
502 }
503
504
515 {
516 assert('is_string($assocId)');
517 assert('is_string($relayState) || is_null($relayState)');
518
520 $session->deleteData('core:idp-ssotime', $this->id.';'.substr($assocId, strpos($assocId, ':') + 1));
521
522 $handler = $this->getLogoutHandler();
523 $handler->onResponse($assocId, $relayState, $error);
524
525 assert('false');
526 }
527
528
536 public function doLogoutRedirect($url)
537 {
538 assert('is_string($url)');
539
540 $state = array(
541 'Responder' => array('SimpleSAML_IdP', 'finishLogoutRedirect'),
542 'core:Logout:URL' => $url,
543 );
544
545 $this->handleLogoutRequest($state, null);
546 assert('false');
547 }
548
549
558 public static function finishLogoutRedirect(SimpleSAML_IdP $idp, array $state)
559 {
560 assert('isset($state["core:Logout:URL"])');
561
563 assert('false');
564 }
565}
$auth
Definition: metadata.php:48
$metadata['__DYNAMIC:1__']
$spEntityId
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
if(!isset($_REQUEST['ReturnTo'])) $returnTo
Definition: authpage.php:16
An exception for terminatinating execution or to throw for unit testing.
static getModuleURL($resource, array $parameters=array())
Get absolute URL to a specified module resource.
Definition: Module.php:303
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
Definition: HTTP.php:962
static getById($authId, $type=null)
Retrieve authentication source.
Definition: Source.php:324
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 getInstance($instancename='simplesaml')
Get a configuration file by its instance name.
Class SimpleSAML_Error_NoPassive.
Definition: NoPassive.php:12
static getByState(array &$state)
Retrieve the IdP "owning" the state.
Definition: IdP.php:152
authenticate(array &$state)
Authenticate the user.
Definition: IdP.php:346
terminateAssociation($assocId)
Remove an SP association.
Definition: IdP.php:248
static finishLogoutRedirect(SimpleSAML_IdP $idp, array $state)
Redirect to a URL after logout.
Definition: IdP.php:558
getId()
Retrieve the ID of this IdP.
Definition: IdP.php:118
isAuthenticated()
Is the current user authenticated?
Definition: IdP.php:262
static postAuth(array $state)
The user is authenticated.
Definition: IdP.php:299
handleLogoutRequest(array &$state, $assocId)
Process a logout request.
Definition: IdP.php:479
handleAuthenticationRequest(array &$state)
Process authentication requests.
Definition: IdP.php:384
getSPName($assocId)
Get SP name.
Definition: IdP.php:178
addAssociation(array $association)
Add an SP association.
Definition: IdP.php:219
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:165
getLogoutHandler()
Find the logout handler of this IdP.
Definition: IdP.php:434
reauthenticate(array &$state)
Re-authenticate the user.
Definition: IdP.php:368
__construct($id)
Initialize an IdP.
Definition: IdP.php:64
doLogoutRedirect($url)
Log out, then redirect to a URL.
Definition: IdP.php:536
getAssociations()
Retrieve list of SP associations.
Definition: IdP.php:236
handleLogoutResponse($assocId, $relayState, SimpleSAML_Error_Exception $error=null)
Process a logout response.
Definition: IdP.php:514
static $idpCache
Definition: IdP.php:19
finishLogout(array &$state)
Finish the logout operation.
Definition: IdP.php:460
$associationGroup
Definition: IdP.php:38
static postAuthProc(array $state)
Called after authproc has run.
Definition: IdP.php:273
static getById($id)
Retrieve an IdP by ID.
Definition: IdP.php:131
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
const DATA_TIMEOUT_SESSION_END
This is a timeout value for setData, which indicates that the data should never be deleted,...
Definition: Session.php:26
static getSessionFromRequest()
Retrieves the current session.
Definition: Session.php:243
$error
Definition: Error.php:17
$relayState
if(!isset($associations[$assocId])) $association
if(!isset($_REQUEST['association'])) $assocId
$idpMetadata
$spMetadata
$session
$url
$idp
Definition: prp.php:13
$handler
$globalConfig