Skip to content
This repository was archived by the owner on Sep 19, 2022. It is now read-only.

Commit 40e1acf

Browse files
author
Dominik František Bučík
authored
Merge pull request #168 from BaranekD/wayf_sp_name
feat: WAYF displays a name of the service
2 parents 0cd38c7 + e3808ed commit 40e1acf

File tree

8 files changed

+205
-8
lines changed

8 files changed

+205
-8
lines changed

config-templates/module_perun.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@
261261
'entityIds' => [],
262262
],
263263
],
264+
'display_sp_name' => false,
265+
// interface needed just in case of display_sp_name => true
266+
'interface' => 'rpc',
264267
],
265268

266269
'warning_test_sp_config' => [

config-templates/perun_attributes.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
'ldap' => 'dynamicRegistration',
2323
'type' => 'bool',
2424
],
25+
'perunFacilityAttr_entityID' => [
26+
'rpc' => 'urn:perun:facility:attribute-def:def:entityID',
27+
'ldap' => 'entityID',
28+
'type' => 'string',
29+
],
2530
'perunFacilityAttr_OIDCClientID' => [
2631
'rpc' => 'urn:perun:facility:attribute-def:def:OIDCClientID',
2732
'ldap' => 'OIDCClientID',
@@ -62,6 +67,11 @@
6267
'ldap' => 'capabilities',
6368
'type' => 'map',
6469
],
70+
'perunFacilityAttr_spname' => [
71+
'rpc' => 'urn:perun:facility:attribute-def:def:serviceName',
72+
'ldap' => 'serviceName',
73+
'type' => 'map',
74+
],
6575

6676
/*
6777
* USER ATTRIBUTES

dictionaries/disco.definition.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
{
22
"header": {
33
"en": "Choose how to log in",
4-
"cs": "Vyberte čím se chcete přihlásit"
4+
"cs": "Vyberte, čím se chcete přihlásit"
5+
},
6+
"header_display_service": {
7+
"en": "to the service",
8+
"cs": "ke službě"
59
},
610
"institutional_account": {
711
"en": "your institutional account",

lib/Adapter.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,18 @@ abstract public function getVoAttributesValues($vo, $attributes);
126126
abstract public function getFacilityAttribute($facility, $attrName);
127127

128128
/**
129-
* @param string $spEntityId
129+
* @param string $spEntityId Value of the entityID identifier
130130
* @return Facility facility
131131
*/
132-
abstract public function getFacilityByEntityId($spEntityId);
132+
abstract public function getFacilityByEntityId($spEntityId, $entityIdAttr);
133+
134+
/**
135+
* @param string $clientId Value of the client_id identifier
136+
* @param string $clientIdAttr Internal name of the client_id attribute, defaults to 'perunFacilityAttr_OIDCClientID'
137+
* this key has to be present in the attribute map configuration (see perun_attributes.php config template)
138+
* @return Facility facility
139+
*/
140+
abstract public function getFacilityByClientId($clientId, $clientIdAttr);
133141

134142
/**
135143
* @param string $spEntityId entity id of the sp

lib/AdapterLdap.php

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,15 @@ public function getFacilitiesByEntityId($spEntityId)
284284
return $this->fallbackAdapter->getFacilitiesByEntityId($spEntityId);
285285
}
286286

287-
public function getFacilityByEntityId($spEntityId)
287+
public function getFacilityByEntityId($spEntityId, $entityIdAttr = 'perunFacilityAttr_entityID')
288288
{
289+
$attrName = AttributeUtils::getLdapAttrName($entityIdAttr);
290+
if (empty($attributeName)) {
291+
throw new Exception("No attribute configuration in LDAP found for attribute ${entityIdAttr}");
292+
}
289293
$ldapResult = $this->connector->searchForEntity(
290294
$this->ldapBase,
291-
'(&(objectClass=perunFacility)(entityID=' . $spEntityId . '))',
295+
"(&(objectClass=perunFacility)(${attrName}=${spEntityId}))",
292296
[self::PERUN_FACILITY_ID, self::CN, self::DESCRIPTION]
293297
);
294298

@@ -307,6 +311,33 @@ public function getFacilityByEntityId($spEntityId)
307311
return $facility;
308312
}
309313

314+
public function getFacilityByClientId($clientId, $clientIdAttr = 'perunFacilityAttr_OIDCClientID')
315+
{
316+
$attrName = AttributeUtils::getLdapAttrName($clientIdAttr);
317+
if (empty($attributeName)) {
318+
throw new Exception("No attribute configuration in LDAP found for attribute ${clientIdAttr}");
319+
}
320+
$ldapResult = $this->connector->searchForEntity(
321+
$this->ldapBase,
322+
"(&(objectClass=perunFacility)(${attrName}=${clientId}))",
323+
[self::PERUN_FACILITY_ID, self::CN, self::DESCRIPTION]
324+
);
325+
326+
if (empty($ldapResult)) {
327+
Logger::warning('perun:AdapterLdap: No facility with clientId \'' . $clientId . '\' found.');
328+
return null;
329+
}
330+
331+
$facility = new Facility(
332+
$ldapResult[self::PERUN_FACILITY_ID][0],
333+
$ldapResult[self::CN][0],
334+
$ldapResult[self::DESCRIPTION][0],
335+
$clientId
336+
);
337+
338+
return $facility;
339+
}
340+
310341
public function getEntitylessAttribute($attrName)
311342
{
312343
return $this->fallbackAdapter->getEntitylessAttribute($attrName);

lib/AdapterRpc.php

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,10 @@ public function getFacilityAdmins($facility)
323323

324324
public function getFacilityAttribute($facility, $attrName)
325325
{
326+
$attrNameRpc = AttributeUtils::getRpcAttrName($attrName);
326327
$perunAttr = $this->connector->get('attributesManager', 'getAttribute', [
327328
'facility' => $facility->getId(),
328-
'attributeName' => $attrName,
329+
'attributeName' => $attrNameRpc,
329330
]);
330331

331332
return $perunAttr['value'];
@@ -368,10 +369,14 @@ public function getUsersGroupsOnFacility($spEntityId, $userId)
368369
return $this->removeDuplicateEntities($groups);
369370
}
370371

371-
public function getFacilityByEntityId($spEntityId)
372+
public function getFacilityByEntityId($spEntityId, $entityIdAttr = 'perunFacilityAttr_entityID')
372373
{
374+
$attributeName = AttributeUtils::getRpcAttrName($entityIdAttr);
375+
if (empty($attributeName)) {
376+
throw new Exception("No attribute configuration in RPC found for attribute ${entityIdAttr}");
377+
}
373378
$perunAttr = $this->connector->get('facilitiesManager', 'getFacilitiesByAttribute', [
374-
'attributeName' => 'urn:perun:facility:attribute-def:def:entityID',
379+
'attributeName' => $attributeName,
375380
'attributeValue' => $spEntityId,
376381
]);
377382

@@ -390,6 +395,30 @@ public function getFacilityByEntityId($spEntityId)
390395
return new Facility($perunAttr[0]['id'], $perunAttr[0]['name'], $perunAttr[0]['description'], $spEntityId);
391396
}
392397

398+
public function getFacilityByClientId($clientId, $clientIdAttr = 'perunFacilityAttr_OIDCClientID')
399+
{
400+
$attributeName = AttributeUtils::getRpcAttrName($clientIdAttr);
401+
if (empty($attributeName)) {
402+
throw new Exception("No attribute configuration in RPC found for attribute ${clientIdAttr}");
403+
}
404+
$perunAttr = $this->connector->get('facilitiesManager', 'getFacilitiesByAttribute', [
405+
'attributeName' => $attributeName,
406+
'attributeValue' => $clientId,
407+
]);
408+
409+
if (empty($perunAttr)) {
410+
Logger::warning('perun:AdapterRpc: No facility with clientId \'' . $clientId . '\' found.');
411+
return null;
412+
}
413+
414+
if (count($perunAttr) > 1) {
415+
Logger::warning('perun:AdapterRpc: There is more than one facility with clientId \'' . $clientId . '.');
416+
return null;
417+
}
418+
419+
return new Facility($perunAttr[0]['id'], $perunAttr[0]['name'], $perunAttr[0]['description'], $clientId);
420+
}
421+
393422
/**
394423
* Returns member by User and Vo
395424
*

lib/Disco.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ class Disco extends PowerIdPDisco
3333
# ROOT CONFIGURATION ENTRY
3434
public const WAYF = 'wayf_config';
3535

36+
public const INTERFACE = 'interface';
37+
38+
public const RPC = 'rpc';
39+
3640
# CONFIGURATION ENTRIES
3741
public const BOXED = 'boxed';
3842

@@ -42,6 +46,8 @@ class Disco extends PowerIdPDisco
4246

4347
public const DISABLE_WHITELISTING = 'disable_whitelisting';
4448

49+
public const DISPLAY_SP = 'display_sp_name';
50+
4551
# CONFIGURATION ENTRIES IDP BLOCKS
4652
public const IDP_BLOCKS = 'idp_blocks_config';
4753

@@ -121,6 +127,22 @@ class Disco extends PowerIdPDisco
121127

122128
public const SAML_SP_SSO = 'saml:sp:sso';
123129

130+
public const NAME = 'name';
131+
132+
# DISPLAY SERVICE NAME KEYS
133+
134+
public const CLIENT_ID_PREFIX = 'urn:cesnet:proxyidp:client_id:';
135+
136+
public const SERVICE_NAME_ATTR = 'service_name_attr';
137+
138+
public const SERVICE_NAME_DEFAULT_ATTR_NAME = 'perunFacilityAttr_spname';
139+
140+
public const CLIENT_ID_ATTR = 'client_id_attr';
141+
142+
public const ENTITY_ID_ATTR = 'entity_id_attr';
143+
144+
# VARIABLES
145+
124146
private $originalsp;
125147

126148
private array $originalAuthnContextClassRef = [];
@@ -129,6 +151,12 @@ class Disco extends PowerIdPDisco
129151

130152
private $perunModuleConfiguration;
131153

154+
private $displaySpName;
155+
156+
private $spName;
157+
158+
private $adapter;
159+
132160
private $proxyIdpEntityId;
133161

134162
public function __construct(array $metadataSets, $instance)
@@ -156,12 +184,14 @@ public function __construct(array $metadataSets, $instance)
156184
if ($state !== null) {
157185
if (isset($state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::AUTHN_CONTEXT_CLASS_REF])) {
158186
$this->originalAuthnContextClassRef = $state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::AUTHN_CONTEXT_CLASS_REF];
187+
159188
$this->removeAuthContextClassRefWithPrefixes($state);
160189
if (isset($state['IdPMetadata']['entityid'])) {
161190
$this->proxyIdpEntityId = $state['IdPMetadata']['entityid'];
162191
}
163192
State::saveState($state, self::SAML_SP_SSO);
164193
}
194+
165195
$e = explode('=', $returnURL)[0];
166196
$newReturnURL = $e . '=' . urlencode($id);
167197
$_GET[self::RETURN] = $newReturnURL;
@@ -239,6 +269,11 @@ public function handleRequest()
239269
}
240270

241271
$t = new DiscoTemplate($this->config);
272+
$this->displaySpName = $this->wayfConfiguration->getBoolean(self::DISPLAY_SP, false);
273+
if ($this->displaySpName) {
274+
$this->fillSpName($t);
275+
}
276+
242277
$t->data[self::ORIGINAL_SP] = $this->originalsp;
243278
$t->data[self::IDP_LIST] = $this->idplistStructured($idpList);
244279
$t->data[self::PREFERRED_IDP] = $preferredIdP;
@@ -248,6 +283,8 @@ public function handleRequest()
248283
$t->data[self::AUTHN_CONTEXT_CLASS_REF] = $this->originalAuthnContextClassRef;
249284
$t->data[self::WARNING_ATTRIBUTES] = $warningAttributes;
250285
$t->data[self::WAYF] = $this->wayfConfiguration;
286+
$t->data[self::NAME] = $this->spName;
287+
$t->data[self::DISPLAY_SP] = $this->displaySpName;
251288
$t->show();
252289
}
253290

@@ -844,4 +881,73 @@ private static function constructSearchData($idpMetadata): string
844881

845882
return strtolower(str_replace('"', '', iconv('UTF-8', 'US-ASCII//TRANSLIT', $res)));
846883
}
884+
885+
private static function substrInArray($needle, array $haystack)
886+
{
887+
foreach ($haystack as $item) {
888+
if (strpos($item, $needle) !== false) {
889+
return $item;
890+
}
891+
}
892+
893+
return null;
894+
}
895+
896+
private function fillSpName($t)
897+
{
898+
$clientIdWithPrefix = self::substrInArray(self::CLIENT_ID_PREFIX, $this->originalAuthnContextClassRef);
899+
900+
$this->adapter = Adapter::getInstance($this->wayfConfiguration->getString(self::INTERFACE, self::RPC));
901+
try {
902+
if ($clientIdWithPrefix !== null) {
903+
$parts = explode(':', $clientIdWithPrefix);
904+
$clientId = end($parts);
905+
906+
$clientIdAttr = $this->wayfConfiguration->getString(self::CLIENT_ID_ATTR, null);
907+
if ($clientIdAttr === null) {
908+
$facility = $this->adapter->getFacilityByClientId($clientId);
909+
} else {
910+
$facility = $this->adapter->getFacilityByClientId($clientId, $clientIdAttr);
911+
}
912+
913+
if ($facility !== null) {
914+
$spNameAttrName = $this->wayfConfiguration->getString(
915+
self::SERVICE_NAME_ATTR,
916+
self::SERVICE_NAME_DEFAULT_ATTR_NAME
917+
);
918+
$spNameMap = $this->adapter->getFacilityAttribute($facility, $spNameAttrName);
919+
if (! empty($spNameMap)) {
920+
$this->spName = $t->getTranslation($spNameMap);
921+
}
922+
}
923+
} else {
924+
$entityId = $this->originalsp['entityid'];
925+
$entityIdAttr = $this->wayfConfiguration->getString(self::ENTITY_ID_ATTR, null);
926+
if ($entityIdAttr === null) {
927+
$facility = $this->adapter->getFacilityByEntityId($entityId);
928+
} else {
929+
$facility = $this->adapter->getFacilityByEntityId($entityId, $entityIdAttr);
930+
}
931+
932+
if ($facility !== null) {
933+
$spNameAttr = $this->wayfConfiguration->getString(
934+
self::SERVICE_NAME_ATTR,
935+
self::SERVICE_NAME_DEFAULT_ATTR_NAME
936+
);
937+
$spNameMap = $this->adapter->getFacilityAttribute($facility, $spNameAttr);
938+
if (! empty($spNameMap)) {
939+
$this->spName = $t->getTranslation($spNameMap);
940+
}
941+
}
942+
if (empty($entityId)) {
943+
if (! empty($this->originalsp[self::NAME])) {
944+
$this->spName = $t->translate->getTranslation($this->originalsp[self::NAME]);
945+
}
946+
}
947+
}
948+
} catch (\Exception $e) {
949+
Logger::warning("Fill SP name - caught exception ${e}");
950+
//OK, we will just display the disco
951+
}
952+
}
847953
}

themes/perun/perun/disco-tpl.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
Module::getModuleUrl('perun/res/css/disco.css') . '" />';
3030

3131
$wayfConfig = $this->data[Disco::WAYF];
32+
$displaySpName = $this->data[Disco::DISPLAY_SP];
33+
$spName = $this->data[Disco::NAME];
3234

3335
$translateModule = $wayfConfig->getString(Disco::TRANSLATE_MODULE, 'disco');
3436
$addInstitutionConfig = $wayfConfig->getConfigItem(Disco::ADD_INSTITUTION, null);
@@ -55,6 +57,10 @@
5557
$this->data['header'] = $this->t('{perun:disco:add_institution}');
5658
} else {
5759
$this->data['header'] = $this->t('{perun:disco:header}');
60+
61+
if ($displaySpName && ! empty($spName)) {
62+
$this->data['header'] .= ' ' . $this->t('{perun:disco:header_display_service}') . ' ' . $spName;
63+
}
5864
}
5965

6066
$this->includeAtTemplateBase('includes/header.php');

0 commit comments

Comments
 (0)