From f9e8fe2d907836df552a39736be8c5d75456e35c Mon Sep 17 00:00:00 2001 From: Mads Freek Petersen <freek@wayf.dk> Date: Wed, 4 Feb 2009 17:46:52 +0000 Subject: [PATCH] added support for IsPassive flag in Consent module and in SSOService. If IsPassive is set and Consent requires user interaction an SimpleSAML_Error_NoPassive exception is thrown. SSOService now catches the exception and returns an AuthResponse with NoPassive (which SSP currently can't handle in an orderly way). We expect all processing modules to throw SimpleSAML_Error_NoPassive exceptions if isPassive is true in the state and they require user interaction. ProcessingChain is updated with a new method - processStatePassive which drives the processing filters with isPassive set to true and ignores all SimpleSAML_Error_NoPassive exceptions. This will be used in a forthcoming release of a consent administration module. Written by Jacob Christiansen and Mads Freek from wayf.dk. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1237 44740490-163a-0410-bde0-09ae8108e29a --- lib/SimpleSAML/Auth/ProcessingChain.php | 34 ++++++++++++++++++++ modules/consent/lib/Auth/Process/Consent.php | 5 +++ www/saml2/idp/SSOService.php | 25 +++++++++++++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/SimpleSAML/Auth/ProcessingChain.php b/lib/SimpleSAML/Auth/ProcessingChain.php index 153190c20..2f00bba45 100644 --- a/lib/SimpleSAML/Auth/ProcessingChain.php +++ b/lib/SimpleSAML/Auth/ProcessingChain.php @@ -213,6 +213,40 @@ class SimpleSAML_Auth_ProcessingChain { SimpleSAML_Utilities::redirect($state['ReturnURL'], array(self::AUTHPARAM => $id)); } + /** + * Process the given state passivly. + * + * Modules with user interaction are expected to throw an SimpleSAML_Error_NoPassive exception + * which are silently ignored. Exceptions of other types are passed further up the call stack. + * + * This function will only return if processing completes. + * + * @param array &$state The state we are processing. + */ + public function processStatePassive(&$state) { + assert('is_array($state)'); + // Should not be set when calling this method + assert('!array_key_exists("ReturnURL", $state)'); + + // Notify filters about passive request + $state['isPassive'] = TRUE; + + $state[self::FILTERS_INDEX] = $this->filters; + + if (!array_key_exists('UserID', $state)) { + /* No unique user ID present. Attempt to add one. */ + self::addUserID($state); + } + + while (count($state[self::FILTERS_INDEX]) > 0) { + $filter = array_shift($state[self::FILTERS_INDEX]); + try { + $filter->process($state); + + // Ignore SimpleSAML_Error_NoPassive exceptions + } catch (SimpleSAML_Error_NoPassive $e) { } + } + } /** * Retrieve a state which has finished processing. diff --git a/modules/consent/lib/Auth/Process/Consent.php b/modules/consent/lib/Auth/Process/Consent.php index 2b6dbca96..26a35327b 100644 --- a/modules/consent/lib/Auth/Process/Consent.php +++ b/modules/consent/lib/Auth/Process/Consent.php @@ -163,6 +163,11 @@ class sspmod_consent_Auth_Process_Consent extends SimpleSAML_Auth_ProcessingFilt $state['consent:focus'] = $this->focus; $state['consent:checked'] = $this->checked; + /* User interaction nessesary. Throw exception on isPassive request */ + if (isset($state['isPassive']) && $state['isPassive'] == TRUE) { + throw new SimpleSAML_Error_NoPassive('noPassive'); + } + /* Save state and redirect. */ $id = SimpleSAML_Auth_State::saveState($state, 'consent:request'); $url = SimpleSAML_Module::getModuleURL('consent/getconsent.php'); diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php index b1fe63cfc..191d892d8 100644 --- a/www/saml2/idp/SSOService.php +++ b/www/saml2/idp/SSOService.php @@ -284,9 +284,32 @@ if($needAuth && !$isPassive) { 'Attributes' => $attributes, 'Destination' => $spmetadata, 'Source' => $idpmetadata, + 'isPassive' => $isPassive, ); - $pc->processState($authProcState); + try { + $pc->processState($authProcState); + } catch (SimpleSAML_Error_NoPassive $e) { + /* Any user interaction is considered harmfull if isPassive is set to TRUE - even + * giving consent. + * If the user is authenticated but a processing filter needs user interaction + * we expect a SimpleSAML_Error_NoPassive exception to be thrown. We then send + * back the proper respons. + */ + try { + /* Generate an SAML 2.0 AuthNResponse message + * With statusCode: urn:oasis:names:tc:SAML:2.0:status:NoPassive + */ + $ar = new SimpleSAML_XML_SAML20_AuthnResponse($config, $metadata); + $authnResponseXML = $ar->generate($idpentityid, $requestcache['Issuer'], $requestcache['RequestID'], NULL, NULL, 'NoPassive'); + + /* Sending the AuthNResponse using HTTP-Post SAML 2.0 binding. */ + $httppost = new SimpleSAML_Bindings_SAML20_HTTPPost($config, $metadata); + $httppost->sendResponse($authnResponseXML, $idpentityid, $requestcache['Issuer'], $requestcache['RelayState']); + } catch(Exception $exception) { + SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATEAUTHNRESPONSE', $exception); + } + } $requestcache['AuthProcState'] = $authProcState; } -- GitLab