diff --git a/attributealter/feideaccess.php b/attributealter/feideaccess.php
new file mode 100644
index 0000000000000000000000000000000000000000..92132294e16b37fa0f7c4ad92ba4dd037d3d2f7a
--- /dev/null
+++ b/attributealter/feideaccess.php
@@ -0,0 +1,32 @@
+<?php
+function attributealter_feideaccess(&$attributes, $spEntityId = null, $idpEntityId = null) {
+	assert('$spEntityId !== NULL');
+	assert('$idpEntityId !== NULL');
+
+	$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+	$spMetadata = $metadata->getMetadata($spEntityId, 'saml20-sp-remote');
+	if(!array_key_exists('feide.allowedorgs', $spMetadata)) {
+		SimpleSAML_Logger::info('FEIDE access control: No limits set for SP: ' . $spEntityId);
+		return;
+	}
+	$allowedOrgs = $spMetadata['feide.allowedorgs'];
+
+	if(!array_key_exists('eduPersonPrincipalName', $attributes)) {
+		throw new Exception('FEIDE access control requires the eduPersonPrincipalName to be present.');
+	}
+
+	$eppn = $attributes['eduPersonPrincipalName'][0];
+	$org = explode('@', $eppn);
+	$org = $org[1];
+
+	if(!in_array($org, $allowedOrgs, TRUE)) {
+		$session = SimpleSAML_Session::getInstance();
+		SimpleSAML_Logger::error('FEIDE access control: Organization "' . $org .
+			'" not in list of allowed organization for SP "' . $spEntityId . '".');
+		SimpleSAML_Utilities::fatalError($session->getTrackId(), 'NOACCESS');
+	}
+
+	SimpleSAML_Logger::info('FEIDE access control: Organization "' . $org .
+		'" is allowed for SP "' . $spEntityId . '".');
+}
+?>
\ No newline at end of file
diff --git a/templates/default/login-feide.php b/templates/default/login-feide.php
index 9f301a80c9ae7c895e7785a53771e23ccdfca919..6d71242bfd16c566cfae8af6bb1360e9c3000d6b 100644
--- a/templates/default/login-feide.php
+++ b/templates/default/login-feide.php
@@ -19,7 +19,8 @@ $this->includeAtTemplateBase('includes/header.php');
 			<legend>Choose your home organization</legend>
 				<select name="org" tabindex="1">
 				<?php
-					foreach ($this->data['ldapconfig'] AS $key => $entry) {
+					foreach ($this->data['allowedorgs'] AS $key) {
+						$entry = $this->data['ldapconfig'][$key];
 						echo '<option ' 
 						. ($key == $this->data['org'] ? 'selected="selected" ' : '')
 						. 'value="' . htmlspecialchars($key) . '">' . htmlspecialchars($entry['description']) . '</option>';
diff --git a/www/auth/login-feide.php b/www/auth/login-feide.php
index b5bf2c304de9167422c0a6c03211c8348f5b82a9..739fbd274d8720338caacccfac3625586602fcdf 100644
--- a/www/auth/login-feide.php
+++ b/www/auth/login-feide.php
@@ -63,6 +63,16 @@ try {
 $spentityid = $authrequestcache['Issuer'];
 $spmetadata = $metadata->getMetadata($spentityid, 'saml20-sp-remote');
 
+/*
+ * Find the list of allowed organizations.
+ */
+$allowedOrgs = array_keys($ldaporgconfig);
+if(array_key_exists('feide.allowedorgs', $spmetadata)) {
+	assert('is_array($spmetadata["feide.allowedorgs"])');
+	$allowedOrgs = array_intersect($spmetadata['feide.allowedorgs'], $allowedOrgs);
+}
+
+
 $error = null;
 $attributes = array();
 
@@ -95,7 +105,12 @@ if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'change_org') {
 	$selectorg = true;
 }
 
-
+/*
+ * The user may have previously selected an organization which the SP doesn't allow. Correct this.
+ */
+if ($selectorg === FALSE && !in_array($org, $allowedOrgs, TRUE)) {
+	$selectorg = TRUE;
+}
 
 
 if (isset($_REQUEST['username'])) {	
@@ -260,13 +275,31 @@ $t->data['relaystate'] = $_REQUEST['RelayState'];
 $t->data['ldapconfig'] = $ldaporgconfig;
 $t->data['protocol'] = $protocol;
 $t->data['authid'] = $authid;
-$t->data['splogo'] = $spmetadata['logo'];
-$t->data['spdesc'] = $spmetadata['description'];
-$t->data['spname'] = $spmetadata['name'];
-$t->data['contact'] = $spmetadata['contact'];
+
+if(array_key_exists('logo', $spmetadata)) {
+	$t->data['splogo'] = $spmetadata['logo'];
+} else {
+	$t->data['splogo'] = NULL;
+}
+if(array_key_exists('description', $spmetadata)) {
+	$t->data['spdesc'] = $spmetadata['description'];
+} else {
+	$t->data['spdesc'] = NULL;
+}
+if(array_key_exists('name', $spmetadata)) {
+	$t->data['spname'] = $spmetadata['name'];
+} else {
+	$t->data['spname'] = NULL;
+}
+if(array_key_exists('contact', $spmetadata)) {
+	$t->data['contact'] = $spmetadata['contact'];
+} else {
+	$t->data['contact'] = NULL;
+}
 
 $t->data['selectorg'] = $selectorg;
 $t->data['org'] = $org;
+$t->data['allowedorgs'] = $allowedOrgs;
 $t->data['error'] = $error;
 if (isset($error)) {
 	$t->data['username'] = $_POST['username'];