ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
IdP.php
Go to the documentation of this file.
1<?php
2
11{
17 private static $idpCache = array();
18
24 private $id;
25
35
41 private $config;
42
48 private $authSource;
49
57 private function __construct($id)
58 {
59 assert(is_string($id));
60
61 $this->id = $id;
62
65
66 if (substr($id, 0, 6) === 'saml2:') {
67 if (!$globalConfig->getBoolean('enable.saml20-idp', false)) {
68 throw new SimpleSAML_Error_Exception('enable.saml20-idp disabled in config.php.');
69 }
70 $this->config = $metadata->getMetaDataConfig(substr($id, 6), 'saml20-idp-hosted');
71 } elseif (substr($id, 0, 6) === 'saml1:') {
72 if (!$globalConfig->getBoolean('enable.shib13-idp', false)) {
73 throw new SimpleSAML_Error_Exception('enable.shib13-idp disabled in config.php.');
74 }
75 $this->config = $metadata->getMetaDataConfig(substr($id, 6), 'shib13-idp-hosted');
76 } elseif (substr($id, 0, 5) === 'adfs:') {
77 if (!$globalConfig->getBoolean('enable.adfs-idp', false)) {
78 throw new SimpleSAML_Error_Exception('enable.adfs-idp disabled in config.php.');
79 }
80 $this->config = $metadata->getMetaDataConfig(substr($id, 5), 'adfs-idp-hosted');
81
82 try {
83 // this makes the ADFS IdP use the same SP associations as the SAML 2.0 IdP
84 $saml2EntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted');
85 $this->associationGroup = 'saml2:'.$saml2EntityId;
86 } catch (Exception $e) {
87 // probably no SAML 2 IdP configured for this host. Ignore the error
88 }
89 } else {
90 assert(false);
91 }
92
93 if ($this->associationGroup === null) {
94 $this->associationGroup = $this->id;
95 }
96
97 $auth = $this->config->getString('auth');
99 $this->authSource = new \SimpleSAML\Auth\Simple($auth);
100 } else {
101 throw new SimpleSAML_Error_Exception('No such "'.$auth.'" auth source found.');
102 }
103 }
104
105
111 public function getId()
112 {
113 return $this->id;
114 }
115
116
124 public static function getById($id)
125 {
126 assert(is_string($id));
127
128 if (isset(self::$idpCache[$id])) {
129 return self::$idpCache[$id];
130 }
131
132 $idp = new self($id);
133 self::$idpCache[$id] = $idp;
134 return $idp;
135 }
136
137
145 public static function getByState(array &$state)
146 {
147 assert(isset($state['core:IdP']));
148
149 return self::getById($state['core:IdP']);
150 }
151
152
158 public function getConfig()
159 {
160 return $this->config;
161 }
162
163
171 public function getSPName($assocId)
172 {
173 assert(is_string($assocId));
174
175 $prefix = substr($assocId, 0, 4);
176 $spEntityId = substr($assocId, strlen($prefix) + 1);
178
179 if ($prefix === 'saml') {
180 try {
181 $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
182 } catch (Exception $e) {
183 try {
184 $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'shib13-sp-remote');
185 } catch (Exception $e) {
186 return null;
187 }
188 }
189 } else {
190 if ($prefix === 'adfs') {
191 $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'adfs-sp-remote');
192 } else {
193 return null;
194 }
195 }
196
197 if ($spMetadata->hasValue('name')) {
198 return $spMetadata->getLocalizedString('name');
199 } elseif ($spMetadata->hasValue('OrganizationDisplayName')) {
200 return $spMetadata->getLocalizedString('OrganizationDisplayName');
201 } else {
202 return array('en' => $spEntityId);
203 }
204 }
205
206
212 public function addAssociation(array $association)
213 {
214 assert(isset($association['id']));
215 assert(isset($association['Handler']));
216
217 $association['core:IdP'] = $this->id;
218
220 $session->addAssociation($this->associationGroup, $association);
221 }
222
223
229 public function getAssociations()
230 {
232 return $session->getAssociations($this->associationGroup);
233 }
234
235
242 {
243 assert(is_string($assocId));
244
246 $session->terminateAssociation($this->associationGroup, $assocId);
247 }
248
249
255 public function isAuthenticated()
256 {
257 return $this->authSource->isAuthenticated();
258 }
259
260
266 public static function postAuthProc(array $state)
267 {
268 assert(is_callable($state['Responder']));
269
270 if (isset($state['core:SP'])) {
272 $session->setData(
273 'core:idp-ssotime',
274 $state['core:IdP'].';'.$state['core:SP'],
275 time(),
277 );
278 }
279
280 call_user_func($state['Responder'], $state);
281 assert(false);
282 }
283
284
292 public static function postAuth(array $state)
293 {
295
296 if (!$idp->isAuthenticated()) {
297 throw new SimpleSAML_Error_Exception('Not authenticated.');
298 }
299
300 $state['Attributes'] = $idp->authSource->getAttributes();
301
302 if (isset($state['SPMetadata'])) {
303 $spMetadata = $state['SPMetadata'];
304 } else {
305 $spMetadata = array();
306 }
307
308 if (isset($state['core:SP'])) {
310 $previousSSOTime = $session->getData('core:idp-ssotime', $state['core:IdP'].';'.$state['core:SP']);
311 if ($previousSSOTime !== null) {
312 $state['PreviousSSOTimestamp'] = $previousSSOTime;
313 }
314 }
315
316 $idpMetadata = $idp->getConfig()->toArray();
317
319
320 $state['ReturnCall'] = array('SimpleSAML_IdP', 'postAuthProc');
321 $state['Destination'] = $spMetadata;
322 $state['Source'] = $idpMetadata;
323
324 $pc->processState($state);
325
327 }
328
329
339 private function authenticate(array &$state)
340 {
341 if (isset($state['isPassive']) && (bool) $state['isPassive']) {
342 throw new \SimpleSAML\Module\saml\Error\NoPassive('Passive authentication not supported.');
343 }
344
345 $this->authSource->login($state);
346 }
347
348
361 private function reauthenticate(array &$state)
362 {
363 $sourceImpl = $this->authSource->getAuthSource();
364 if ($sourceImpl === null) {
365 throw new SimpleSAML_Error_Exception('No such auth source defined.');
366 }
367
368 $sourceImpl->reauthenticate($state);
369 }
370
371
377 public function handleAuthenticationRequest(array &$state)
378 {
379 assert(isset($state['Responder']));
380
381 $state['core:IdP'] = $this->id;
382
383 if (isset($state['SPMetadata']['entityid'])) {
384 $spEntityId = $state['SPMetadata']['entityid'];
385 } elseif (isset($state['SPMetadata']['entityID'])) {
386 $spEntityId = $state['SPMetadata']['entityID'];
387 } else {
388 $spEntityId = null;
389 }
390 $state['core:SP'] = $spEntityId;
391
392 // first, check whether we need to authenticate the user
393 if (isset($state['ForceAuthn']) && (bool) $state['ForceAuthn']) {
394 // force authentication is in effect
395 $needAuth = true;
396 } else {
397 $needAuth = !$this->isAuthenticated();
398 }
399
400 $state['IdPMetadata'] = $this->getConfig()->toArray();
401 $state['ReturnCallback'] = array('SimpleSAML_IdP', 'postAuth');
402
403 try {
404 if ($needAuth) {
405 $this->authenticate($state);
406 assert(false);
407 } else {
408 $this->reauthenticate($state);
409 }
410 $this->postAuth($state);
411 } catch (SimpleSAML_Error_Exception $e) {
413 } catch (Exception $e) {
416 }
417 }
418
419
427 public function getLogoutHandler()
428 {
429 // find the logout handler
430 $logouttype = $this->getConfig()->getString('logouttype', 'traditional');
431 switch ($logouttype) {
432 case 'traditional':
433 $handler = 'SimpleSAML\IdP\TraditionalLogoutHandler';
434 break;
435 case 'iframe':
436 $handler = 'SimpleSAML\IdP\IFrameLogoutHandler';
437 break;
438 default:
439 throw new SimpleSAML_Error_Exception('Unknown logout handler: '.var_export($logouttype, true));
440 }
441
442 return new $handler($this);
443 }
444
445
453 public function finishLogout(array &$state)
454 {
455 assert(isset($state['Responder']));
456
458 call_user_func($state['Responder'], $idp, $state);
459 assert(false);
460 }
461
462
472 public function handleLogoutRequest(array &$state, $assocId)
473 {
474 assert(isset($state['Responder']));
475 assert(is_string($assocId) || $assocId === null);
476
477 $state['core:IdP'] = $this->id;
478 $state['core:TerminatedAssocId'] = $assocId;
479
480 if ($assocId !== null) {
483 $session->deleteData('core:idp-ssotime', $this->id.':'.$state['saml:SPEntityId']);
484 }
485
486 // terminate the local session
487 $id = SimpleSAML_Auth_State::saveState($state, 'core:Logout:afterbridge');
488 $returnTo = SimpleSAML\Module::getModuleURL('core/idp/resumelogout.php', array('id' => $id));
489
490 $this->authSource->logout($returnTo);
491
492 $handler = $this->getLogoutHandler();
493 $handler->startLogout($state, $assocId);
494 assert(false);
495 }
496
497
508 {
509 assert(is_string($assocId));
510 assert(is_string($relayState) || $relayState === null);
511
513 $session->deleteData('core:idp-ssotime', $this->id.';'.substr($assocId, strpos($assocId, ':') + 1));
514
515 $handler = $this->getLogoutHandler();
516 $handler->onResponse($assocId, $relayState, $error);
517
518 assert(false);
519 }
520
521
529 public function doLogoutRedirect($url)
530 {
531 assert(is_string($url));
532
533 $state = array(
534 'Responder' => array('SimpleSAML_IdP', 'finishLogoutRedirect'),
535 'core:Logout:URL' => $url,
536 );
537
538 $this->handleLogoutRequest($state, null);
539 assert(false);
540 }
541
542
551 public static function finishLogoutRedirect(SimpleSAML_IdP $idp, array $state)
552 {
553 assert(isset($state['core:Logout:URL']));
554
556 assert(false);
557 }
558}
$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:220
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
Definition: HTTP.php:959
static getById($authId, $type=null)
Retrieve authentication source.
Definition: Source.php:340
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.
static getByState(array &$state)
Retrieve the IdP "owning" the state.
Definition: IdP.php:145
authenticate(array &$state)
Authenticate the user.
Definition: IdP.php:339
terminateAssociation($assocId)
Remove an SP association.
Definition: IdP.php:241
static finishLogoutRedirect(SimpleSAML_IdP $idp, array $state)
Redirect to a URL after logout.
Definition: IdP.php:551
getId()
Retrieve the ID of this IdP.
Definition: IdP.php:111
isAuthenticated()
Is the current user authenticated?
Definition: IdP.php:255
static postAuth(array $state)
The user is authenticated.
Definition: IdP.php:292
handleLogoutRequest(array &$state, $assocId)
Process a logout request.
Definition: IdP.php:472
handleAuthenticationRequest(array &$state)
Process authentication requests.
Definition: IdP.php:377
getSPName($assocId)
Get SP name.
Definition: IdP.php:171
addAssociation(array $association)
Add an SP association.
Definition: IdP.php:212
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:158
getLogoutHandler()
Find the logout handler of this IdP.
Definition: IdP.php:427
reauthenticate(array &$state)
Re-authenticate the user.
Definition: IdP.php:361
__construct($id)
Initialize an IdP.
Definition: IdP.php:57
doLogoutRedirect($url)
Log out, then redirect to a URL.
Definition: IdP.php:529
getAssociations()
Retrieve list of SP associations.
Definition: IdP.php:229
handleLogoutResponse($assocId, $relayState, SimpleSAML_Error_Exception $error=null)
Process a logout response.
Definition: IdP.php:507
static $idpCache
Definition: IdP.php:17
finishLogout(array &$state)
Finish the logout operation.
Definition: IdP.php:453
$associationGroup
Definition: IdP.php:34
static postAuthProc(array $state)
Called after authproc has run.
Definition: IdP.php:266
static getById($id)
Retrieve an IdP by ID.
Definition: IdP.php:124
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:241
$auth
Definition: fileserver.php:48
$relayState
if(!isset($associations[$assocId])) $association
if(!isset($_REQUEST['association'])) $assocId
$idpMetadata
$spMetadata
$session
$url
$idp
Definition: prp.php:13
$handler
$globalConfig