From e5aa6821b5566ef34875b233c7d7d9bdd2d82b84 Mon Sep 17 00:00:00 2001 From: Jaime Perez Crespo <jaime.perez@uninett.no> Date: Tue, 21 Jul 2015 12:16:25 +0200 Subject: [PATCH] Bugfix No data about previous authentication is stored if authentication was not started at the SP (IdP-first flow). That makes the replay protection measures fail, leading to an ugly exception show to the user. Fix that. Additionally, give precedence to the RelayState configured in the local metadata, as the one received together with the SAML response may not even be an URL. This resolves #230. --- modules/saml/www/sp/saml2-acs.php | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/modules/saml/www/sp/saml2-acs.php b/modules/saml/www/sp/saml2-acs.php index 68751e374..ff495904a 100644 --- a/modules/saml/www/sp/saml2-acs.php +++ b/modules/saml/www/sp/saml2-acs.php @@ -60,7 +60,12 @@ if ($prevAuth !== NULL && $prevAuth['id'] === $response->getId() && $prevAuth['i * instead of displaying a confusing error message. */ SimpleSAML_Logger::info('Duplicate SAML 2 response detected - ignoring the response and redirecting the user to the correct page.'); - \SimpleSAML\Utils\HTTP::redirectTrustedURL($prevAuth['redirect']); + if (isset($prevAuth['redirect'])) { + \SimpleSAML\Utils\HTTP::redirectTrustedURL($prevAuth['redirect']); + } + + SimpleSAML_Logger::info('No RelayState or ReturnURL available, cannot redirect.'); + throw new SimpleSAML_Error_Exception('Duplicate assertion received.'); } $idpMetadata = array(); @@ -90,7 +95,11 @@ if (!empty($stateId)) { $state = array( 'saml:sp:isUnsolicited' => TRUE, 'saml:sp:AuthId' => $sourceId, - 'saml:sp:RelayState' => \SimpleSAML\Utils\HTTP::checkURLAllowed($response->getRelayState()), + 'saml:sp:RelayState' => \SimpleSAML\Utils\HTTP::checkURLAllowed($spMetadata->getString( + 'RelayState', + $response->getRelayState() + ) + ), ); } @@ -196,17 +205,17 @@ if ($expire !== NULL) { $state['Expire'] = $expire; } +// note some information about the authentication, in case we receive the same response again +$state['saml:sp:prevAuth'] = array( + 'id' => $response->getId(), + 'issuer' => $idp, +); if (isset($state['SimpleSAML_Auth_Default.ReturnURL'])) { - /* Just note some information about the authentication, in case we receive the - * same response again. - */ - $state['saml:sp:prevAuth'] = array( - 'id' => $response->getId(), - 'issuer' => $idp, - 'redirect' => $state['SimpleSAML_Auth_Default.ReturnURL'], - ); - $state['PersistentAuthData'][] = 'saml:sp:prevAuth'; + $state['saml:sp:prevAuth']['redirect'] = $state['SimpleSAML_Auth_Default.ReturnURL']; +} elseif (isset($state['saml:sp:RelayState'])) { + $state['saml:sp:prevAuth']['redirect'] = $state['saml:sp:RelayState']; } +$state['PersistentAuthData'][] = 'saml:sp:prevAuth'; $source->handleResponse($state, $idp, $attributes); assert('FALSE'); -- GitLab