From fe056c4f0e5251ad7c6de86d4b16f5c7516f2666 Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Mon, 30 Jun 2008 13:02:56 +0000
Subject: [PATCH] SAML2_SP: Add support for OnError error handler.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@727 44740490-163a-0410-bde0-09ae8108e29a
---
 www/saml2/sp/AssertionConsumerService.php | 38 ++++++++++++++++++-----
 www/saml2/sp/initSSO.php                  |  8 +++++
 2 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/www/saml2/sp/AssertionConsumerService.php b/www/saml2/sp/AssertionConsumerService.php
index d76f815bf..9e24a9c90 100644
--- a/www/saml2/sp/AssertionConsumerService.php
+++ b/www/saml2/sp/AssertionConsumerService.php
@@ -35,7 +35,36 @@ try {
 	$binding = new SimpleSAML_Bindings_SAML20_HTTPPost($config, $metadata);
 	$authnResponse = $binding->decodeResponse($_POST);
 	
-	$authnResponse->process();
+	$result = $authnResponse->process();
+
+	/* Fetch the request information if it exists, fall back to RelayState if not. */
+	$requestId = $authnResponse->getInResponseTo();
+	$info = $session->getData('SAML2:SP:SSO:Info', $requestId);
+	if($info === NULL) {
+		/* Fall back to RelayState. */
+		$info = array();
+		$info['RelayState'] = $authnResponse->getRelayState();
+		if(!isset($info['RelayState'])) {
+			/* RelayState missing. */
+			SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NORELAYSTATE');
+		}
+	}
+
+	/* Check status code, call OnError handler on error. */
+	if($result === FALSE) {
+		/* Not successful. */
+		$statusCode = $authnResponse->findstatus();
+		if(array_key_exists('OnError', $info)) {
+			/* We have an error handler. Return the error to it. */
+			SimpleSAML_Utilities::redirect($info['OnError'], array('StatusCode' => $statusCode));
+		} else {
+			/* We don't have an error handler. Show an error page. */
+			SimpleSAML_Utilities::fatalError($session->getTrackID(), 'RESPONSESTATUSNOSUCCESS',
+				new Exception("Status = " . $statusCode));
+		}
+	}
+
+	/* Successful authentication. */
 
 	SimpleSAML_Logger::info('SAML2.0 - SP.AssertionConsumerService: Successfully created local session from Authentication Response');
 
@@ -79,12 +108,7 @@ try {
 		
 		
 
-	$relayState = $authnResponse->getRelayState();
-	if (isset($relayState)) {
-		SimpleSAML_Utilities::redirect($relayState);
-	} else {
-		SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NORELAYSTATE');
-	}
+	SimpleSAML_Utilities::redirect($info['RelayState']);
 
 } catch(Exception $exception) {
 	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'PROCESSASSERTION', $exception);
diff --git a/www/saml2/sp/initSSO.php b/www/saml2/sp/initSSO.php
index 61c3d9f19..5b0b095be 100644
--- a/www/saml2/sp/initSSO.php
+++ b/www/saml2/sp/initSSO.php
@@ -84,6 +84,14 @@ try {
 	
 	$httpredirect->sendMessage($req, $spentityid, $idpentityid, $_GET['RelayState']);
 
+	/* Save request information. */
+	$info = array();
+	$info['RelayState'] = $_GET['RelayState'];
+	if(array_key_exists('OnError', $_REQUEST)) {
+		$info['OnError'] = $_REQUEST['OnError'];
+	}
+	$session->setData('SAML2:SP:SSO:Info', $sr->getGeneratedID(), $info);
+
 } catch(Exception $exception) {
 	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'CREATEREQUEST', $exception);
 }
-- 
GitLab