1<?php 2/* 3 * consentAdmin - Consent administration module 4 * 5 * This module enables the user to add and remove consents given for a given 6 * Service Provider. 7 * 8 * The module relies on methods and functions from the Consent module and can 9 * not be user without it. 10 * 11 * Author: Mads Freek <freek@ruc.dk>, Jacob Christiansen <jach@wayf.dk> 12 */ 13 14/* 15 * Runs the processing chain and ignores all filter which have user 16 * interaction. 17 */ 18function driveProcessingChain( 19 $idp_metadata, 20 $source, 21 $sp_metadata, 22 $sp_entityid, 23 $attributes, 24 $userid, 25 $hashAttributes = false, 26 $excludeAttributes = array() 27) { 28 29 /* 30 * Create a new processing chain 31 */ 32 $pc = new SimpleSAML_Auth_ProcessingChain($idp_metadata, $sp_metadata, 'idp'); 33 34 /* 35 * Construct the state. 36 * REMEMBER: Do not set Return URL if you are calling processStatePassive 37 */ 38 $authProcState = array( 39 'Attributes' => $attributes, 40 'Destination' => $sp_metadata, 41 'SPMetadata' => $sp_metadata, 42 'Source' => $idp_metadata, 43 'IdPMetadata' => $idp_metadata, 44 'isPassive' => true, 45 ); 46 /* we're being bridged, so add that info to the state */ 47 if (strpos($source, '-idp-remote|') !== false) { 48 $authProcState['saml:sp:IdP'] = substr($source, strpos($source, '|') + 1); 49 } 50 51 /* 52 * Call processStatePAssive. 53 * We are not interested in any user interaction, only modifications to the attributes 54 */ 55 $pc->processStatePassive($authProcState); 56 57 $attributes = $authProcState['Attributes']; 58 // Remove attributes that do not require consent/should be excluded 59 foreach ($attributes as $attrkey => $attrval) { 60 if (in_array($attrkey, $excludeAttributes)) { 61 unset($attributes[$attrkey]); 62 } 63 } 64 65 /* 66 * Generate identifiers and hashes 67 */ 68 $destination = $sp_metadata['metadata-set'].'|'.$sp_entityid; 69 70 $targeted_id = sspmod_consent_Auth_Process_Consent::getTargetedID($userid, $source, $destination); 71 $attribute_hash = sspmod_consent_Auth_Process_Consent::getAttributeHash($attributes, $hashAttributes); 72 73 SimpleSAML\Logger::info('consentAdmin: user: '.$userid); 74 SimpleSAML\Logger::info('consentAdmin: target: '.$targeted_id); 75 SimpleSAML\Logger::info('consentAdmin: attribute: '.$attribute_hash); 76 77 // Return values 78 return array($targeted_id, $attribute_hash, $attributes); 79} 80 81// Get config object 82$config = SimpleSAML_Configuration::getInstance(); 83$cA_config = SimpleSAML_Configuration::getConfig('module_consentAdmin.php'); 84$authority = $cA_config->getValue('authority'); 85 86$as = new \SimpleSAML\Auth\Simple($authority); 87 88// If request is a logout request 89if (array_key_exists('logout', $_REQUEST)) { 90 $returnURL = $cA_config->getValue('returnURL'); 91 $as->logout($returnURL); 92} 93 94$hashAttributes = $cA_config->getValue('attributes.hash'); 95 96$excludeAttributes = $cA_config->getValue('attributes.exclude', array()); 97 98// Check if valid local session exists 99$as->requireAuth(); 100 101// Get released attributes 102$attributes = $as->getAttributes(); 103 104// Get metadata storage handler 105$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); 106 107/* 108 * Get IdP id and metadata 109 */ 110 111 112$idp_entityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); 113$idp_metadata = $metadata->getMetaData($idp_entityid, 'saml20-idp-hosted'); 114 115// Calc correct source 116if ($as->getAuthData('saml:sp:IdP') !== null) { 117 // from a remote idp (as bridge) 118 $source = 'saml20-idp-remote|'.$as->getAuthData('saml:sp:IdP'); 119} else { 120 // from the local idp 121 $source = $idp_metadata['metadata-set'].'|'.$idp_entityid; 122} 123 124// Get user ID 125$userid_attributename = (isset($idp_metadata['userid.attribute']) && is_string($idp_metadata['userid.attribute'])) ? $idp_metadata['userid.attribute'] : 'eduPersonPrincipalName'; 126 127$userids = $attributes[$userid_attributename]; 128 129if (empty($userids)) { 130 throw new Exception('Could not generate useridentifier for storing consent. Attribute ['. 131 $userid_attributename.'] was not available.'); 132} 133 134$userid = $userids[0]; 135 136// Get all SP metadata 137$all_sp_metadata = $metadata->getList('saml20-sp-remote'); 138 139// Parse action, if any 140$action = null; 141$sp_entityid = null; 142if (!empty($_GET['cv'])) { 143 $sp_entityid = $_GET['cv']; 144} 145if (!empty($_GET['action'])) { 146 $action = $_GET["action"]; 147} 148 149SimpleSAML\Logger::critical('consentAdmin: sp: '.$sp_entityid.' action: '.$action); 150 151// Remove services, whitch have consent disabled 152if (isset($idp_metadata['consent.disable'])) { 153 foreach ($idp_metadata['consent.disable'] AS $disable) { 154 if (array_key_exists($disable, $all_sp_metadata)) { 155 unset($all_sp_metadata[$disable]); 156 } 157 } 158} 159 160SimpleSAML\Logger::info('consentAdmin: '.$idp_entityid); 161 162// Parse consent config 163$consent_storage = sspmod_consent_Store::parseStoreConfig($cA_config->getValue('consentadmin')); 164 165// Calc correct user ID hash 166$hashed_user_id = sspmod_consent_Auth_Process_Consent::getHashedUserID($userid, $source); 167 168// If a checkbox have been clicked 169if ($action !== null && $sp_entityid !== null) { 170 // Get SP metadata 171 $sp_metadata = $metadata->getMetaData($sp_entityid, 'saml20-sp-remote'); 172 173 // Run AuthProc filters 174 list($targeted_id, $attribute_hash, $attributes_new) = driveProcessingChain($idp_metadata, $source, $sp_metadata, 175 $sp_entityid, $attributes, $userid, $hashAttributes, $excludeAttributes); 176 177 // Add a consent (or update if attributes have changed and old consent for SP and IdP exists) 178 if ($action == 'true') { 179 $isStored = $consent_storage->saveConsent($hashed_user_id, $targeted_id, $attribute_hash); 180 if ($isStored) { 181 $res = "added"; 182 } else { 183 $res = "updated"; 184 } 185 // Remove consent 186 } else { 187 if ($action == 'false') { 188 // Got consent, so this is a request to remove it 189 $rowcount = $consent_storage->deleteConsent($hashed_user_id, $targeted_id); 190 if ($rowcount > 0) { 191 $res = "removed"; 192 } 193 // Unknown action (should not happen) 194 } else { 195 SimpleSAML\Logger::info('consentAdmin: unknown action'); 196 $res = "unknown"; 197 } 198 } 199 // init template to enable translation of status messages 200 $template = new SimpleSAML_XHTML_Template($config, 'consentAdmin:consentadminajax.php', 'consentAdmin:consentadmin'); 201 $template->data['res'] = $res; 202 $template->show(); 203 exit; 204} 205 206// Get all consents for user 207$user_consent_list = $consent_storage->getConsents($hashed_user_id); 208 209// Parse list of consents 210$user_consent = array(); 211foreach ($user_consent_list as $c) { 212 $user_consent[$c[0]] = $c[1]; 213} 214 215$template_sp_content = array(); 216 217// Init template 218$template = new SimpleSAML_XHTML_Template($config, 'consentAdmin:consentadmin.php', 'consentAdmin:consentadmin'); 219$translator = $template->getTranslator(); 220$translator->includeLanguageFile('attributes'); // attribute listings translated by this dictionary 221$sp_empty_name = $translator->getTag('sp_empty_name'); 222$sp_empty_description = $translator->getTag('sp_empty_description'); 223 224// Process consents for all SP 225foreach ($all_sp_metadata as $sp_entityid => $sp_values) { 226 // Get metadata for SP 227 $sp_metadata = $metadata->getMetaData($sp_entityid, 'saml20-sp-remote'); 228 229 // Run attribute filters 230 list($targeted_id, $attribute_hash, $attributes_new) = driveProcessingChain($idp_metadata, $source, $sp_metadata, 231 $sp_entityid, $attributes, $userid, $hashAttributes, $excludeAttributes); 232 233 // Check if consent exists 234 if (array_key_exists($targeted_id, $user_consent)) { 235 $sp_status = "changed"; 236 SimpleSAML\Logger::info('consentAdmin: changed'); 237 // Check if consent is valid. (Possible that attributes has changed) 238 if ($user_consent[$targeted_id] == $attribute_hash) { 239 SimpleSAML\Logger::info('consentAdmin: ok'); 240 $sp_status = "ok"; 241 } 242 // Consent does not exists 243 } else { 244 SimpleSAML\Logger::info('consentAdmin: none'); 245 $sp_status = "none"; 246 } 247 248 // Set name of SP 249 if (isset($sp_values['name']) && is_array($sp_values['name'])) { 250 $sp_name = $sp_metadata['name']; 251 } else { 252 if (isset($sp_values['name']) && is_string($sp_values['name'])) { 253 $sp_name = $sp_metadata['name']; 254 } elseif (isset($sp_values['OrganizationDisplayName']) && is_array($sp_values['OrganizationDisplayName'])) { 255 $sp_name = $sp_metadata['OrganizationDisplayName']; 256 } else { 257 $sp_name = $sp_empty_name; 258 } 259 } 260 261 // Set description of SP 262 if (empty($sp_metadata['description']) || !is_array($sp_metadata['description'])) { 263 $sp_description = $sp_empty_description; 264 } else { 265 $sp_description = $sp_metadata['description']; 266 } 267 268 // Add a URL to the service if present in metadata 269 $sp_service_url = isset($sp_metadata['ServiceURL']) ? $sp_metadata['ServiceURL'] : null; 270 271 // Fill out array for the template 272 $sp_list[$sp_entityid] = array( 273 'spentityid' => $sp_entityid, 274 'name' => $sp_name, 275 'description' => $sp_description, 276 'consentStatus' => $sp_status, 277 'consentValue' => $sp_entityid, 278 'attributes_by_sp' => $attributes_new, 279 'serviceurl' => $sp_service_url, 280 ); 281} 282 283$template->data['header'] = 'Consent Administration'; 284$template->data['spList'] = $sp_list; 285$template->data['showDescription'] = $cA_config->getValue('showDescription'); 286$template->show(); 287