From 0f810a7abab8ff2eeecbb63959b2f5836b71a8f2 Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Mon, 13 Jul 2009 09:03:58 +0000 Subject: [PATCH] saml2:SP: Add discovery service support. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1584 44740490-163a-0410-bde0-09ae8108e29a --- modules/saml2/lib/Auth/Source/SP.php | 63 ++++++++++++++++++++++++++-- modules/saml2/www/disco.php | 10 +++++ modules/saml2/www/sp/discoresp.php | 28 +++++++++++++ 3 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 modules/saml2/www/disco.php create mode 100644 modules/saml2/www/sp/discoresp.php diff --git a/modules/saml2/lib/Auth/Source/SP.php b/modules/saml2/lib/Auth/Source/SP.php index 6dc6ce7fa..3af1c5d02 100644 --- a/modules/saml2/lib/Auth/Source/SP.php +++ b/modules/saml2/lib/Auth/Source/SP.php @@ -15,10 +15,17 @@ class sspmod_saml2_Auth_Source_SP extends SimpleSAML_Auth_Source { /** - * The string used to identify our states. + * The identifier for the stage where we have sent a discovery service request. + */ + const STAGE_DISCO = 'saml2:SP-DiscoSent'; + + + /** + * The identifier for the stage where we have sent a SSO request. */ const STAGE_SENT = 'saml2:SP-SSOSent'; + /** * The string used to identify our logout state. */ @@ -82,7 +89,7 @@ class sspmod_saml2_Auth_Source_SP extends SimpleSAML_Auth_Source { if (array_key_exists('idp', $config)) { $this->idp = $config['idp']; } else { - throw new Exception('TODO: Add support for IdP discovery.'); + $this->idp = NULL; } } @@ -100,17 +107,65 @@ class sspmod_saml2_Auth_Source_SP extends SimpleSAML_Auth_Source { /* We are going to need the authId in order to retrieve this authentication source later. */ $state[self::AUTHID] = $this->authId; + if ($this->idp === NULL) { + $this->initDisco($state); + } + + $this->initSSO($this->idp, $state); + } + + + /** + * Send authentication request to specified IdP. + * + * @param string $idp The IdP we should send the request to. + * @param array $state Our state array. + */ + public function initDisco($state) { + assert('is_array($state)'); + + $id = SimpleSAML_Auth_State::saveState($state, self::STAGE_DISCO); + + $config = SimpleSAML_Configuration::getInstance(); + + $discoURL = $config->getString('idpdisco.url.saml20', NULL); + if ($discoURL === NULL) { + /* Fallback to internal discovery service. */ + $discoURL = SimpleSAML_Module::getModuleURL('saml2/disco.php'); + } + + $returnTo = SimpleSAML_Module::getModuleURL('saml2/sp/discoresp.php'); + $returnTo = SimpleSAML_Utilities::addURLparameter($returnTo, array('AuthID' => $id)); + + SimpleSAML_Utilities::redirect($discoURL, array( + 'entityID' => $this->entityId, + 'return' => $returnTo, + 'returnIDParam' => 'idpentityid') + ); + } + + + /** + * Send authentication request to specified IdP. + * + * @param string $idp The IdP we should send the request to. + * @param array $state Our state array. + */ + public function initSSO($idp, $state) { + assert('is_string($idp)'); + assert('is_array($state)'); + $id = SimpleSAML_Auth_State::saveState($state, self::STAGE_SENT); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); - $idpMetadata = $metadata->getMetaData($this->idp, 'saml20-idp-remote'); + $idpMetadata = $metadata->getMetaData($idp, 'saml20-idp-remote'); $config = SimpleSAML_Configuration::getInstance(); $sr = new SimpleSAML_XML_SAML20_AuthnRequest($config, $metadata); $req = $sr->generate($this->entityId, $idpMetadata['SingleSignOnService']); $httpredirect = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata); - $httpredirect->sendMessage($req, $this->entityId, $this->idp, $id); + $httpredirect->sendMessage($req, $this->entityId, $idp, $id); exit(0); } diff --git a/modules/saml2/www/disco.php b/modules/saml2/www/disco.php new file mode 100644 index 000000000..f3e526c5a --- /dev/null +++ b/modules/saml2/www/disco.php @@ -0,0 +1,10 @@ +<?php + +/** + * Builtin IdP discovery service. + */ + +$discoHandler = new SimpleSAML_XHTML_IdPDisco('saml20'); +$discoHandler->handleRequest(); + +?> \ No newline at end of file diff --git a/modules/saml2/www/sp/discoresp.php b/modules/saml2/www/sp/discoresp.php new file mode 100644 index 000000000..0ce9dd907 --- /dev/null +++ b/modules/saml2/www/sp/discoresp.php @@ -0,0 +1,28 @@ +<?php + +/** + * Handler for response from IdP discovery service. + */ + +if (!array_key_exists('AuthID', $_REQUEST)) { + throw new SimpleSAML_Error_BadRequest('Missing AuthID to discovery service response handler'); +} + +if (!array_key_exists('idpentityid', $_REQUEST)) { + throw new SimpleSAML_Error_BadRequest('Missing idpentityid to discovery service response handler'); +} + +$state = SimpleSAML_Auth_State::loadState($_REQUEST['AuthID'], sspmod_saml2_Auth_Source_SP::STAGE_DISCO); + +/* Find authentication source. */ +assert('array_key_exists(sspmod_saml2_Auth_Source_SP::AUTHID, $state)'); +$sourceId = $state[sspmod_saml2_Auth_Source_SP::AUTHID]; + +$source = SimpleSAML_Auth_Source::getById($sourceId); +if ($source === NULL) { + throw new Exception('Could not find authentication source with id ' . $sourceId); +} + +$source->initSSO($_REQUEST['idpentityid'], $state); + +?> \ No newline at end of file -- GitLab