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');
98  if (SimpleSAML_Auth_Source::getById($auth) !== null) {
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 
326  self::postAuthProc($state);
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 
555  \SimpleSAML\Utils\HTTP::redirectTrustedURL($state['core:Logout:URL']);
556  assert(false);
557  }
558 }
handleLogoutRequest(array &$state, $assocId)
Process a logout request.
Definition: IdP.php:472
doLogoutRedirect($url)
Log out, then redirect to a URL.
Definition: IdP.php:529
handleAuthenticationRequest(array &$state)
Process authentication requests.
Definition: IdP.php:377
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
if(!isset($_REQUEST['ReturnTo'])) $returnTo
Definition: authpage.php:16
static getByState(array &$state)
Retrieve the IdP "owning" the state.
Definition: IdP.php:145
static $idpCache
Definition: IdP.php:17
isAuthenticated()
Is the current user authenticated?
Definition: IdP.php:255
static getById($id)
Retrieve an IdP by ID.
Definition: IdP.php:124
static throwException($state, SimpleSAML_Error_Exception $exception)
Throw exception to the state exception handler.
Definition: State.php:343
reauthenticate(array &$state)
Re-authenticate the user.
Definition: IdP.php:361
$spEntityId
$session
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
Definition: HTTP.php:959
$spMetadata
$metadata['__DYNAMIC:1__']
$auth
Definition: fileserver.php:48
handleLogoutResponse($assocId, $relayState, SimpleSAML_Error_Exception $error=null)
Process a logout response.
Definition: IdP.php:507
finishLogout(array &$state)
Finish the logout operation.
Definition: IdP.php:453
static getModuleURL($resource, array $parameters=array())
Get absolute URL to a specified module resource.
Definition: Module.php:220
addAssociation(array $association)
Add an SP association.
Definition: IdP.php:212
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
$relayState
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
getLogoutHandler()
Find the logout handler of this IdP.
Definition: IdP.php:427
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:158
static finishLogoutRedirect(SimpleSAML_IdP $idp, array $state)
Redirect to a URL after logout.
Definition: IdP.php:551
terminateAssociation($assocId)
Remove an SP association.
Definition: IdP.php:241
getId()
Retrieve the ID of this IdP.
Definition: IdP.php:111
authenticate(array &$state)
Authenticate the user.
Definition: IdP.php:339
$globalConfig
getSPName($assocId)
Get SP name.
Definition: IdP.php:171
if(!isset($associations[$assocId])) $association
$idp
Definition: prp.php:13
$associationGroup
Definition: IdP.php:34
$idpMetadata
if(!isset($_REQUEST['association'])) $assocId
__construct($id)
Initialize an IdP.
Definition: IdP.php:57
$url
getAssociations()
Retrieve list of SP associations.
Definition: IdP.php:229
static getById($authId, $type=null)
Retrieve authentication source.
Definition: Source.php:340
$handler
static getSessionFromRequest()
Retrieves the current session.
Definition: Session.php:241
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 postAuthProc(array $state)
Called after authproc has run.
Definition: IdP.php:266
static postAuth(array $state)
The user is authenticated.
Definition: IdP.php:292