diff --git a/docs/simplesamlphp-sp-api.txt b/docs/simplesamlphp-sp-api.txt
index fef97669caf7f8489c06bc2b2bee3ae49fb8a631..90969e1a951c23c69a2335f5a5af371330ab2612 100644
--- a/docs/simplesamlphp-sp-api.txt
+++ b/docs/simplesamlphp-sp-api.txt
@@ -105,7 +105,7 @@ The [`saml:SP`](./saml:sp) authentication source also defines some parameters.
 
     # Send a passive authentication request.
     $auth->login(array(
-        'saml:IsPassive' => TRUE,
+        'isPassive' => TRUE,
         'ErrorURL' => 'https://.../error_handler.php',
     ));
 
diff --git a/lib/SAML2/Assertion.php b/lib/SAML2/Assertion.php
index de3ca91f77db7542a03680fea12b820069d037e9..a12b2a90492acd8c7f4922d64d06e3cf50ccb86f 100644
--- a/lib/SAML2/Assertion.php
+++ b/lib/SAML2/Assertion.php
@@ -131,6 +131,13 @@ class SAML2_Assertion implements SAML2_SignedElement {
 	 */
 	private $authnContext;
 
+	/**
+	 * The list of AuthenticatingAuthorities for this assertion.
+	 *
+	 * @var array
+	 */
+	private $AuthenticatingAuthority;
+
 
 	/**
 	 * The attributes, as an associative array.
@@ -192,6 +199,7 @@ class SAML2_Assertion implements SAML2_SignedElement {
 		$this->attributes = array();
 		$this->nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED;
 		$this->certificates = array();
+		$this->AuthenticatingAuthority = array();
 
 		if ($xml === NULL) {
 			return;
@@ -416,6 +424,8 @@ class SAML2_Assertion implements SAML2_SignedElement {
 		} else {
 			$this->authnContext = trim($accr[0]->textContent);
 		}
+		
+		$this->AuthenticatingAuthority = SAML2_Utils::extractStrings($ac, './saml_assertion:AuthenticatingAuthority');		
 	}
 
 
@@ -874,6 +884,29 @@ class SAML2_Assertion implements SAML2_SignedElement {
 	}
 
 
+	/**
+	 * Retrieve the AuthenticatingAuthority.
+	 *
+	 *
+	 * @return array
+	 */
+	public function getAuthenticatingAuthority() {
+
+		return $this->AuthenticatingAuthority;
+	}
+
+
+	/**
+	 * Set the AuthenticatingAuthority
+	 *
+	 *
+	 * @param array.
+	 */
+	public function setAuthenticatingAuthority($AuthenticatingAuthority) {
+		$this->AuthenticatingAuthority = $AuthenticatingAuthority;
+	}
+
+
 	/**
 	 * Retrieve all attributes.
 	 *
@@ -1105,6 +1138,7 @@ class SAML2_Assertion implements SAML2_SignedElement {
 		$as->appendChild($ac);
 
 		SAML2_Utils::addString($ac, SAML2_Const::NS_SAML, 'saml:AuthnContextClassRef', $this->authnContext);
+		SAML2_Utils::addStrings($ac, SAML2_Const::NS_SAML, 'saml:AuthenticatingAuthority', false, $this->AuthenticatingAuthority);
 	}
 
 
diff --git a/lib/SAML2/AuthnRequest.php b/lib/SAML2/AuthnRequest.php
index 10c7defe360ccc888f5a0e792c07a635676b03f0..dc1c26dc9b131abb8c463fc8263f752a6023c93b 100644
--- a/lib/SAML2/AuthnRequest.php
+++ b/lib/SAML2/AuthnRequest.php
@@ -37,6 +37,21 @@ class SAML2_AuthnRequest extends SAML2_Request {
 	*/
 	private $IDPList = array();
 
+	/**
+	 * The ProxyCount in this request's scoping element
+	 *
+	 * @var int
+	*/
+	private $ProxyCount = null;
+
+	/**
+	 * The RequesterID list in this request's scoping element
+	 *
+	 * @var array
+	*/
+
+	private $RequesterID = array();
+	
 	/**
 	 * The URL of the asertion consumer service where the response should be delivered.
 	 *
@@ -128,13 +143,27 @@ class SAML2_AuthnRequest extends SAML2_Request {
 			$this->requestedAuthnContext = $rac;
 		}
 
-		$idpEntries = SAML2_Utils::xpQuery($xml, './saml_protocol:Scoping/saml_protocol:IDPList/saml_protocol:IDPEntry');
+		$scoping = SAML2_Utils::xpQuery($xml, './saml_protocol:Scoping');
+		if (!empty($scoping)) {
+			$scoping =$scoping[0];
+			
+			if ($scoping->hasAttribute('ProxyCount')) {
+				$this->ProxyCount = (int)$scoping->getAttribute('ProxyCount');
+			}
+			$idpEntries = SAML2_Utils::xpQuery($scoping, './saml_protocol:IDPList/saml_protocol:IDPEntry');
 
-		foreach($idpEntries as $idpEntry) {
-			if (!$idpEntry->hasAttribute('ProviderID')) {
-				throw new Exception("Could not get ProviderID from Scoping/IDPEntry element in AuthnRequest object");
+			foreach($idpEntries as $idpEntry) {
+				if (!$idpEntry->hasAttribute('ProviderID')) {
+					throw new Exception("Could not get ProviderID from Scoping/IDPEntry element in AuthnRequest object");
+				}
+				$this->IDPList[] = $idpEntry->getAttribute('ProviderID');
+			}
+		
+			$requesterIDs = SAML2_Utils::xpQuery($scoping, './saml_protocol:RequesterID');
+			foreach ($requesterIDs as $requesterID) {
+				$this->RequesterID[] = trim($requesterID->textContent);
 			}
-			$this->IDPList[] = $idpEntry->getAttribute('ProviderID');
+
 		}
 	}
 
@@ -234,6 +263,22 @@ class SAML2_AuthnRequest extends SAML2_Request {
 		return $this->IDPList;
 	}
 
+	public function setProxyCount($ProxyCount) {
+		assert('is_int($ProxyCount)');
+		$this->ProxyCount = $ProxyCount;
+	}
+
+	public function getProxyCount() {
+		return $this->ProxyCount;
+	}
+	
+	public function setRequesterID(array $RequesterID) {
+		$this->RequesterID = $RequesterID;
+	}
+
+	public function getRequesterID() {
+		return $this->RequesterID;
+	}
 
 	/**
 	 * Retrieve the value of the AssertionConsumerServiceURL attribute.
@@ -352,16 +397,25 @@ class SAML2_AuthnRequest extends SAML2_Request {
 			}
 		}
 
-		if (count($this->IDPList) > 0) {
+
+		if ($this->ProxyCount !== null || count($this->IDPList) > 0 || count($this->RequesterID) > 0) {
 			$scoping = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'Scoping');
-			$idplist = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'IDPList');
-			foreach ($this->IDPList as $provider) {
-				$idpEntry = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'IDPEntry');
-				$idpEntry->setAttribute('ProviderID', $provider);
-				$idplist->appendChild($idpEntry);
+			if ($this->ProxyCount !== null) {
+				$scoping->setAttribute('ProxyCount', $this->ProxyCount);
+			}
+			if (count($this->IDPList) > 0) {
+				$idplist = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'IDPList');
+				foreach ($this->IDPList as $provider) {
+					$idpEntry = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'IDPEntry');
+					$idpEntry->setAttribute('ProviderID', $provider);
+					$idplist->appendChild($idpEntry);
+				}
+				$scoping->appendChild($idplist);
+				$root->appendChild($scoping);
+			}
+			if (count($this->RequesterID) > 0) {
+				SAML2_Utils::addStrings($scoping, SAML2_Const::NS_SAMLP, 'RequesterID', FALSE, $this->RequesterID);
 			}
-			$scoping->appendChild($idplist);
-			$root->appendChild($scoping);
 		}
 
 		return $root;
diff --git a/lib/SAML2/Const.php b/lib/SAML2/Const.php
index aa90068719a0862d34f432bc0456977470b6cde5..d44a28e0383488b811329770812c425186ba01dc 100644
--- a/lib/SAML2/Const.php
+++ b/lib/SAML2/Const.php
@@ -135,6 +135,12 @@ class SAML2_Const {
 	 */
 	const STATUS_PARTIAL_LOGOUT = 'urn:oasis:names:tc:SAML:2.0:status:PartialLogout';
 
+	/**
+	 * Second-level status code for ProxyCountExceeded.
+	 */
+	const STATUS_PROXY_COUNT_EXCEEDED = 'urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded';
+	
+
 }
 
 ?>
\ No newline at end of file
diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php
index e324e09af0b36d2403ac8e2faa2281703df5bc6f..18f78b75c0d4e37f23e418f9ac54df55e29ffa67 100644
--- a/lib/SimpleSAML/IdP.php
+++ b/lib/SimpleSAML/IdP.php
@@ -393,6 +393,8 @@ class SimpleSAML_IdP {
 		if (isset($state['ForceAuthn']) && (bool)$state['ForceAuthn']) {
 			/* Force authentication is in effect. */
 			$needAuth = TRUE;
+		} elseif (isset($state['saml:IDPList']) && sizeof($state['saml:IDPList']) > 0) {
+			$needAuth = TRUE;
 		} else {
 			$needAuth = !$this->isAuthenticated();
 		}
diff --git a/modules/saml/docs/sp.txt b/modules/saml/docs/sp.txt
index 3164bc6aca13145b5019cd22c37427ffa486d5f7..2d44c0fcc18a4147458b391aaa8782c6f2afe7a0 100644
--- a/modules/saml/docs/sp.txt
+++ b/modules/saml/docs/sp.txt
@@ -22,7 +22,7 @@ All these parameters override the equivalent option from the configuration.
 :   *Note*: SAML 2 specific.
 
 
-`saml:ForceAuthn`
+`ForceAuthnn`
 :   Force authentication allows you to force re-authentication of users even if the user has a SSO session at the IdP.
 
 :   *Note*: SAML 2 specific.
@@ -30,7 +30,7 @@ All these parameters override the equivalent option from the configuration.
 `saml:idp`
 :   The entity ID of the IdP we should send an authentication request to.
 
-`saml:IsPassive`
+`isPassive`
 :   Send a passive authentication request.
 
 :   *Note*: SAML 2 specific.
diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php
index d27a3cd4c26d47914b9f4b444253ffc8343ace99..b8e708738063c66a17409eddb94c3229ce568acd 100644
--- a/modules/saml/lib/Auth/Source/SP.php
+++ b/modules/saml/lib/Auth/Source/SP.php
@@ -175,6 +175,10 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source {
 	 * @param array $state  The state array for the current authentication.
 	 */
 	private function startSSO2(SimpleSAML_Configuration $idpMetadata, array $state) {
+	
+		if (isset($state['saml:ProxyCount']) && $state['saml:ProxyCount'] < 0) {
+			SimpleSAML_Auth_State::throwException($state, new SimpleSAML_Error_ProxyCountExceeded("ProxyCountExceeded"));
+		}
 
 		$ar = sspmod_saml2_Message::buildAuthnRequest($this->metadata, $idpMetadata);
 
@@ -190,12 +194,12 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source {
 			$ar->setRequestedAuthnContext(array('AuthnContextClassRef' => $accr));
 		}
 
-		if (isset($state['saml:ForceAuthn'])) {
-			$ar->setForceAuthn((bool)$state['saml:ForceAuthn']);
+		if (isset($state['ForceAuthnn'])) {
+			$ar->setForceAuthn((bool)$state['ForceAuthn']);
 		}
 
-		if (isset($state['saml:IsPassive'])) {
-			$ar->setIsPassive((bool)$state['saml:IsPassive']);
+		if (isset($state['isPassive'])) {
+			$ar->setIsPassive((bool)$state['isPassive']);
 		}
 
 		if (isset($state['saml:NameIDPolicy'])) {
@@ -205,12 +209,37 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source {
 			));
 		}
 
-
+		if (isset($state['saml:IDPList'])) {
+			$IDPList = $state['saml:IDPList'];
+		}
+		
+		$ar->setIDPList(array_unique(array_merge($this->metadata->getArray('IDPList', array()), 
+												$idpMetadata->getArray('IDPList', array()),
+												(array) $IDPList)));
+		
+		if (isset($state['saml:ProxyCount']) && $state['saml:ProxyCount'] !== null) {
+			$ar->setProxyCount($state['saml:ProxyCount']);
+		} elseif ($idpMetadata->getInteger('ProxyCount', null) !== null) {
+			$ar->setProxyCount($idpMetadata->getInteger('ProxyCount', null));
+		} elseif ($this->metadata->getInteger('ProxyCount', null) !== null) {
+			$ar->setProxyCount($this->metadata->getInteger('ProxyCount', null));
+		}
+		
+		$requesterID = array();
+		if (isset($state['saml:RequesterID'])) {
+			$requesterID = $state['saml:RequesterID'];
+		}
+		
+		if (isset($state['core:SP'])) {
+			$requesterID[] = $state['core:SP'];
+		}
+		
+		$ar->setRequesterID($requesterID);
+		
 		$id = SimpleSAML_Auth_State::saveState($state, 'saml:sp:sso', TRUE);
 		$ar->setId($id);
 
 		SimpleSAML_Logger::debug('Sending SAML 2 AuthnRequest to ' . var_export($idpMetadata->getString('entityid'), TRUE));
-
 		$b = new SAML2_HTTPRedirect();
 		$b->setDestination(sspmod_SAML2_Message::getDebugDestination());
 		$b->send($ar);
@@ -291,6 +320,10 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source {
 			$idp = (string)$state['saml:idp'];
 		}
 
+		if ($idp === NULL && isset($state['saml:IDPList']) && sizeof($state['saml:IDPList']) == 1) {
+			$idp = $state['saml:IDPList'][0];
+		}
+
 		if ($idp === NULL) {
 			$this->startDisco($state);
 			assert('FALSE');
@@ -374,7 +407,7 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source {
 		assert('is_string($idp)');
 		assert('array_key_exists("LogoutState", $state)');
 		assert('array_key_exists("saml:logout:Type", $state["LogoutState"])');
-
+		
 		$idpMetadata = $this->getIdpMetadata($idp);
 
 		$spMetadataArray = $this->metadata->toArray();
diff --git a/modules/saml/lib/IdP/SAML2.php b/modules/saml/lib/IdP/SAML2.php
index e9c365450a124b9b8089d97881b4a1af85f76646..e1bafa37e9303baf3dfa0e3b5f9dc3d9fb3c304b 100644
--- a/modules/saml/lib/IdP/SAML2.php
+++ b/modules/saml/lib/IdP/SAML2.php
@@ -48,6 +48,10 @@ class sspmod_saml_IdP_SAML2 {
 
 		$assertion = sspmod_saml2_Message::buildAssertion($idpMetadata, $spMetadata, $attributes, $consumerURL);
 		$assertion->setInResponseTo($requestId);
+		
+		if (isset($state['saml:AuthenticatingAuthority'])) {
+			$assertion->setAuthenticatingAuthority($state['saml:AuthenticatingAuthority']);
+		}
 
 		/* Create the session association (for logout). */
 		$association = array(
@@ -242,6 +246,9 @@ class sspmod_saml_IdP_SAML2 {
 
 			$requestId = $request->getId();
 			$IDPList = $request->getIDPList();
+			$ProxyCount = $request->getProxyCount();
+			if ($ProxyCount !== null) $ProxyCount--;
+			$RequesterID = $request->getRequesterID();
 			$forceAuthn = $request->getForceAuthn();
 			$isPassive = $request->getIsPassive();
 			$consumerURL = $request->getAssertionConsumerServiceURL();
@@ -285,6 +292,7 @@ class sspmod_saml_IdP_SAML2 {
 		}
 
 		$IDPList = array_unique(array_merge($IDPList, $spMetadata->getArrayizeString('IDPList', array())));
+		if ($ProxyCount == null) $ProxyCount = $spMetadata->getInteger('ProxyCount', null);
 
 		if (!$forceAuthn) {
 			$forceAuthn = $spMetadata->getBoolean('ForceAuthn', FALSE);
@@ -311,7 +319,9 @@ class sspmod_saml_IdP_SAML2 {
 			'saml:RelayState' => $relayState,
 			'saml:RequestId' => $requestId,
 			'saml:IDPList' => $IDPList,
-			'ForceAuthn' => $forceAuthn,
+			'saml:ProxyCount' => $ProxyCount,
+			'saml:RequesterID' => $RequesterID,
+			'ForceAuthnn' => $forceAuthn,
 			'isPassive' => $isPassive,
 			'saml:ConsumerURL' => $consumerURL,
 			'saml:Binding' => $protocolBinding,
diff --git a/modules/saml/www/sp/saml2-acs.php b/modules/saml/www/sp/saml2-acs.php
index 0de7f2fb3571b9fede87643c3d5c395d0c1230d8..d9ef345c1d69f1217a2935ab0a10529dc6f7a58b 100644
--- a/modules/saml/www/sp/saml2-acs.php
+++ b/modules/saml/www/sp/saml2-acs.php
@@ -32,7 +32,6 @@ if (!empty($stateId)) {
 	);
 }
 
-
 $idp = $response->getIssuer();
 if ($idp === NULL) {
 	throw new Exception('Missing <saml:Issuer> in message delivered to AssertionConsumerService.');
@@ -63,6 +62,9 @@ $logoutState = array(
 	'saml:logout:SessionIndex' => $sessionIndex,
 	);
 $state['LogoutState'] = $logoutState;
+$state['saml:AuthenticatingAuthority'] = $assertion->getAuthenticatingAuthority();
+$state['saml:AuthenticatingAuthority'][] = $idp;
+$state['PersistentAuthData'][] = 'saml:AuthenticatingAuthority';
 
 $source->handleResponse($state, $idp, $assertion->getAttributes());
 assert('FALSE');
diff --git a/modules/saml2/lib/Error.php b/modules/saml2/lib/Error.php
index cdb017916249eaff7d590a1856deee54a627592d..1c9e11ccc05b8e7d57c76a4420cb350d94289c63 100644
--- a/modules/saml2/lib/Error.php
+++ b/modules/saml2/lib/Error.php
@@ -112,6 +112,13 @@ class sspmod_saml2_Error extends SimpleSAML_Error_Exception {
 				$exception->getMessage(),
 				$exception
 				);
+		} elseif ($exception instanceof SimpleSAML_Error_ProxyCountExceeded) {
+			$e = new self(
+				SAML2_Const::STATUS_RESPONDER,
+				SAML2_Const::STATUS_PROXY_COUNT_EXCEEDED,
+				$exception->getMessage(),
+				$exception
+				);
 
 		} else {
 			$e = new self(