diff --git a/lib/SimpleSAML/Auth/ProcessingChain.php b/lib/SimpleSAML/Auth/ProcessingChain.php index 153190c20f4bad638b5ce77d78e1c65a1d6aa666..2f00bba4589d46154d002b0196438caaa4d57978 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 2b6dbca96956164a34d18d4226a961c63fd18e97..26a35327bedf07f8f822b29e401bd28d858a9a83 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 b1fe63cfc69a05ea90c89060b2f90003dc79ee6a..191d892d8e786b546683c8d2c5ff9f6a926b03e7 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; }