diff --git a/lib/SAML2/AuthnRequest.php b/lib/SAML2/AuthnRequest.php
index 897b08e028ea2cdf96c9bd4e920ec259195bf93b..475afb87781a8fad36777f8ae93b18fe5a3c8fa9 100644
--- a/lib/SAML2/AuthnRequest.php
+++ b/lib/SAML2/AuthnRequest.php
@@ -30,6 +30,12 @@ class SAML2_AuthnRequest extends SAML2_Request {
 	 */
 	private $isPassive;
 
+	/**
+	 * The list of providerIDs in this request's scoping element
+	 *
+	 * @var array
+	*/
+	private $IDPList = array();
 
 	/**
 	 * The URL of the asertion consumer service where the response should be delivered.
@@ -75,6 +81,7 @@ class SAML2_AuthnRequest extends SAML2_Request {
 		}
 
 		$nameIdPolicy = SAML2_Utils::xpQuery($xml, './saml_protocol:NameIDPolicy');
+
 		if (!empty($nameIdPolicy)) {
 			$nameIdPolicy = $nameIdPolicy[0];
 			if ($nameIdPolicy->hasAttribute('Format')) {
@@ -87,6 +94,15 @@ class SAML2_AuthnRequest extends SAML2_Request {
 				$this->nameIdPolicy['AllowCreate'] = SAML2_Utils::parseBoolean($nameIdPolicy, 'AllowCreate', FALSE);
 			}
 		}
+		
+		$idpEntries = SAML2_Utils::xpQuery($xml, './saml_protocol: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");
+			}
+			$this->IDPList[] = $idpEntry->getAttribute('ProviderID');
+		}
 	}
 
 
@@ -161,6 +177,31 @@ class SAML2_AuthnRequest extends SAML2_Request {
 	}
 
 
+	/**
+	 * This function sets the scoping for the request
+	 * See Core 3.4.1.2 for the definition of scoping
+	 * Currently we only support an IDPList of idpEntries
+	 * and only the required ProviderID in an IDPEntry
+	 * $providerIDs is an array of Entity Identifiers
+	 *
+	 */
+	public function setIDPList($IDPList) {
+		assert('is_array($IDPList)');
+		$this->IDPList = $IDPList;
+	}
+
+
+	/**
+	 * This function retrieves the list of providerIDs from this authentication request.
+	 * Currently we only support a list of ipd ientity id's.
+	 * @return The list of idpidentityids from the request
+	 */
+	 
+	public function getIDPList() {
+		return $this->IDPList;
+	}
+
+
 	/**
 	 * Retrieve the value of the AssertionConsumerServiceURL attribute.
 	 *
@@ -230,6 +271,18 @@ class SAML2_AuthnRequest extends SAML2_Request {
 			$root->setAttribute('ProtocolBinding', $this->protocolBinding);
 		}
 
+		if (count($this->IDPList) > 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);
+			}
+			$scoping->appendChild($idplist);
+			$root->appendChild($scoping);
+		}
+
 		if (!empty($this->nameIdPolicy)) {
 			$nameIdPolicy = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'NameIDPolicy');
 			if (array_key_exists('Format', $this->nameIdPolicy)) {
diff --git a/lib/SimpleSAML/XHTML/IdPDisco.php b/lib/SimpleSAML/XHTML/IdPDisco.php
index d694111e336a4c1517331b9e9df4a55354286001..ac873df19949ba7b2e878caa8ee8ec2d1d420289 100644
--- a/lib/SimpleSAML/XHTML/IdPDisco.php
+++ b/lib/SimpleSAML/XHTML/IdPDisco.php
@@ -70,7 +70,13 @@ class SimpleSAML_XHTML_IdPDisco {
 	 */
 	protected $returnIdParam;
 
-
+	/**
+	 * The list of scoped idp's. The intersection between the metadata idpList
+	 * and scopedIDPList (given as a $_GET IDPList[] parameter) is presented to
+	 * the user. If the intersection is empty the metadata idpList is used.
+	 */
+	protected $scopedIDPList = array();
+	
 	/**
 	 * The URL the user should be redirected to after choosing an IdP.
 	 */
@@ -133,6 +139,10 @@ class SimpleSAML_XHTML_IdPDisco {
 			$this->setIdPentityID = NULL;
 		}
 
+		if (array_key_exists('IDPList', $_GET)) {
+			$this->scopedIDPList = $_GET['IDPList'];
+		}
+
 	}
 
 
@@ -418,7 +428,15 @@ class SimpleSAML_XHTML_IdPDisco {
 		return $idpList;
 	}
 
-
+	/**
+	 * Return the list of scoped idp
+	 *
+	 * @return array  Array of idp entities
+	 */
+	protected function getScopedIDPList() {
+		return $this->scopedIDPList;
+	}
+	
 	/**
 	 * Handles a request to this discovery service.
 	 *
@@ -460,6 +478,11 @@ class SimpleSAML_XHTML_IdPDisco {
 		$idpList = $this->getIdPList();
 		$preferredIdP = $this->getRecommendedIdP();
 
+		$idpintersection = array_intersect(array_keys($idpList), $this->getScopedIDPlist());
+		if (sizeof($idpintersection) > 0) {
+			$idpList = array_intersect_key($idpList, array_fill_keys($idpintersection, NULL));
+		}
+
 		/*
 		 * Make use of an XHTML template to present the select IdP choice to the user.
 		 * Currently the supported options is either a drop down menu or a list view.
diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php
index d9d78884cfe74d316737484bc9f997e4c308c77d..4fac005ddf749bcb0bc9011eded9560304096538 100644
--- a/www/saml2/idp/SSOService.php
+++ b/www/saml2/idp/SSOService.php
@@ -94,7 +94,9 @@ function handleError(Exception $exception) {
 /*
  * Initiate some variables
  */
-$isPassive = FALSE;
+$isPassive = $forceAuthn = FALSE;
+
+$IDPList = array(); 
 
 /*
  * If the SAMLRequest query parameter is set, we got an incoming Authentication Request 
@@ -136,6 +138,17 @@ if (isset($_REQUEST['SAMLRequest'])) {
 		);
 			
 
+		$spentityid = $requestcache['Issuer'];
+		$spmetadata = $metadata->getMetaData($spentityid, 'saml20-sp-remote');
+
+		$IDPList = $authnrequest->getIDPList();
+
+		if(array_key_exists('IDPList', $spmetadata)) {
+			$IDPList = array_unique(array_merge($IDPList, $spmetadata['IDPList']));
+		}
+		
+		$requestcache['IDPList'] = $IDPList;
+		
 		/*
 		 * Handle the ForceAuthn option.
 		 */
@@ -143,8 +156,6 @@ if (isset($_REQUEST['SAMLRequest'])) {
 		/* The default value is FALSE. */
 		$forceAuthn = FALSE;
 
-		$spentityid = $requestcache['Issuer'];
-		$spmetadata = $metadata->getMetaData($spentityid, 'saml20-sp-remote');
 		if(array_key_exists('ForceAuthn', $spmetadata)) {
 			/* The ForceAuthn flag is set in the metadata for this SP. */
 			$forceAuthn = $spmetadata['ForceAuthn'];
@@ -177,8 +188,9 @@ if (isset($_REQUEST['SAMLRequest'])) {
 			 */
 			$requestcache['NeedAuthentication'] = TRUE;
 		}
+		$requestcache['IsPassive'] = $isPassive;
+		$requestcache['ForceAuthn'] = $forceAuthn;
 
-		
 		SimpleSAML_Logger::info('SAML2.0 - IdP.SSOService: Incomming Authentication request: '.$issuer.' id '.$requestid);
 	
 	} catch(Exception $exception) {
@@ -287,12 +299,16 @@ if(SimpleSAML_Auth_Source::getById($idpmetadata['auth']) !== NULL) {
  * endpoint - then the session is authenticated and set, and the user is redirected back with a RequestID
  * parameter so we can retrieve the cached information from the request.
  */
+ 
 if (!isset($session) || !$session->isValid($authority) ) {
 	/* We don't have a valid session. */
 	$needAuth = TRUE;
 } elseif (array_key_exists('NeedAuthentication', $requestcache) && $requestcache['NeedAuthentication']) {
 	/* We have a valid session, but ForceAuthn is on. */
 	$needAuth = TRUE;
+} elseif ((sizeof($IDPList) > 0 && $session->getidp() !== null && !in_array($session->getidp(), $IDPList))) {
+	/* we do have a valid session but not with one of the scoped idps. */
+	$needAuth = TRUE;
 } else {
 	/* We have a valid session. */
 	$needAuth = FALSE;
@@ -400,7 +416,14 @@ if($needAuth && !$isPassive) {
 		$attributes = $authProcState['Attributes'];
 
 		
-		
+		$host = SimpleSAML_Utilities::getSelfHost();;
+		preg_match("/^(\w+)/", $host, $d);
+		if ($d[1] && $d[1] != 'wayf') {
+			setcookie($d[1], "ok", 0, "/", ".wayf.ruc.dk");
+			setcookie('current', $d[1], 0, "/", ".wayf.ruc.dk");
+		}
+
+
 
 		/*
 		 * Save the time we authenticated to this SP. This can be used later to detect an
diff --git a/www/saml2/sp/initSSO.php b/www/saml2/sp/initSSO.php
index 1dad4aa0ecfe34141088bdf07a081f36201cc08a..b9d1b30096e9c38b0fee3d99927528552032195d 100644
--- a/www/saml2/sp/initSSO.php
+++ b/www/saml2/sp/initSSO.php
@@ -29,16 +29,48 @@ try {
 	$idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getString('default-saml20-idp', NULL) ;
 	$spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID();
 
-	if($idpentityid === NULL) {
-		/* We are going to need the SP metadata to determine which IdP discovery service we should use. */
-		$spmetadata = $metadata->getMetaDataCurrent('saml20-sp-hosted');
+	$isPassive  = isset($_GET['IsPassive']) && ($_GET['IsPassive'] === 'true' || $_GET['IsPassive'] === '1');
+	$forceAuthn = isset($_GET['ForceAuthn']) && ($_GET['ForceAuthn'] === 'true' || $_GET['ForceAuthn'] === '1');
+
+	/* We are going to need the SP metadata to determine which IdP discovery service we should use.
+	   And for checking for scoping parameters. */
+	$spmetadata = $metadata->getMetaDataCurrent('saml20-sp-hosted');
+
+	$IDPList = array();
+
+	/* Configured idp overrides one given by Scope */
+	if($idpentityid === NULL && array_key_exists('idpentityid', $spmetadata)) {
+		$idpentityid = $spmetadata['idpentityid'];
 	}
 
+	/* AuthId is set if we are on the sp side on a proxy/bridge */
+	$authid = isset($_GET['AuthId']) ? $_GET['AuthId'] : FALSE;
+	if ($authid) {
+		$authrequestcache = $session->getAuthnRequest('saml2', $authid);
+		$isPassive  = $isPassive || $authrequestcache['IsPassive'];
+		$forceAuthn = $forceAuthn || $authrequestcache['ForceAuthn'];
+
+		/* keep the IDPList, it MUST be sent it to the next idp,
+		   we are only allowed to add idps */
+		if (isset($authrequestcache['IDPList']) && is_array($authrequestcache['IDPList'])) {
+			$IDPList = $authrequestcache['IDPList'];
+		}
+		if ($idpentityid === NULL) {
+			/* only consider ProviderIDs we know ... */
+	
+			$reachableIDPs = array_intersect($IDPList, array_keys($metadata->getList()));
+
+			if (sizeof($reachableIDPs) === 1) {
+				$idpentityid = array_shift($reachableIDPs);
+			}
+		}
+	}
+	
+
 } catch (Exception $exception) {
 	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
 }
 
-
 /*
  * If no IdP can be resolved, send the user to the SAML 2.0 Discovery Service
  */
@@ -49,6 +81,7 @@ if ($idpentityid === NULL) {
 	/* Which IdP discovery service should we use? Can be set in SP metadata or in global configuration.
 	 * Falling back to builtin discovery service.
 	 */
+
 	if(array_key_exists('idpdisco.url', $spmetadata)) {
 		$discourl = $spmetadata['idpdisco.url'];
 	} elseif($config->getString('idpdisco.url.saml20', NULL) !== NULL) {
@@ -74,12 +107,18 @@ if ($idpentityid === NULL) {
 		);
 	}
 
-
-	SimpleSAML_Utilities::redirect($discourl, array(
+	$discoparameters = array(
 		'entityID' => $spentityid,
 		'return' => SimpleSAML_Utilities::selfURL(),
-		'returnIDParam' => 'idpentityid')
-	);
+		'returnIDParam' => 'idpentityid');
+		
+	$discoparameters['isPassive'] = $isPassive;
+	
+	if (sizeof($reachableIDPs) > 0) {
+		$discoparameters['IDPList'] = $reachableIDPs;
+	}
+
+	SimpleSAML_Utilities::redirect($discourl, $discoparameters);
 }
 
 
@@ -98,9 +137,19 @@ try {
 	$ar->setProtocolBinding(SAML2_Const::BINDING_HTTP_POST);
 	$ar->setRelayState($_REQUEST['RelayState']);
 
-	if (isset($_GET['IsPassive'])) {
-		$ar->setIsPassive((bool)$_GET['IsPassive']);
+	$ar->setIsPassive($isPassive);
+	$ar->setForceAuthn($forceAuthn);
+
+	if(array_key_exists('IDPList', $spmetadata)) {
+		$IDPList = array_unique(array_merge($IDPList, $spmetadata['IDPList']));
 	}
+	
+	if (isset($_GET['IDPList']) && !empty($_GET['IDPList'])) {
+		$providers = $_GET['IDPList'];
+		if (!is_array($providers)) $providers = array($providers);
+		$IDPList = array_merge($IDPList, $providers);
+	};
+	$ar->setIDPList($IDPList);
 
 	/* Save request information. */
 	$info = array();