From 77edcb038f2b396c3487f6f5d3a01b590ea72ec4 Mon Sep 17 00:00:00 2001 From: gregcorbett Date: Wed, 18 May 2022 08:03:16 +0000 Subject: [PATCH 1/6] Re-add redirection for unauthenticated users - Based on the original check made in the ShibToken. - https://github.com/GOCDB/gocdb/blob/5.8.1/lib/Authentication/AuthTokens/ShibAuthToken.php#L174 - it was removed from the ShibToken: - to allow the case where shib authentication fails but another mechanism (X.509, OIDC) succeeds. As such, the check shouldn't be added back to the ShibToken. - because we thought we'd be at the point where we could enforce authentication in apache and not need to in GOCDB. We aren't at that point yet - and we may not want to go there, prefering to enforce authentication in both apache and GOCDB for safety. --- .../components/Get_User_Principle.php | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/htdocs/web_portal/components/Get_User_Principle.php b/htdocs/web_portal/components/Get_User_Principle.php index 98c64a004..b46f8abb1 100644 --- a/htdocs/web_portal/components/Get_User_Principle.php +++ b/htdocs/web_portal/components/Get_User_Principle.php @@ -116,7 +116,12 @@ function Get_User_AuthToken(){ MyStaticAuthTokenHolder::getInstance()->setAuthToken($auth); return $auth; } - return null; + + // We don't want the portal to be exposed without authentication (even + // though no actual info is displayed to an unauthenticated user), + // so if we have not set the principle/userDetails, + // re-direct to our Discovery Service. + redirectUserToDiscoveryPage(); } /** @@ -190,7 +195,12 @@ function Get_User_Principle(){ } return $principleString; } - return null; + + // We don't want the portal to be exposed without authentication (even + // though no actual info is displayed to an unauthenticated user), + // so if we have not set the principle/userDetails, + // re-direct to our Discovery Service. + redirectUserToDiscoveryPage(); } /** @@ -217,9 +227,21 @@ function Get_User_Principle_PI() { } } + # Returning null here is necessary, because parts of the API are exposed + # publically, without authentication. return null; } +/* + * Prevent the current page from being loaded and redirect the user + * to the IdP discovery page (a.k.a the landing page). + */ +function redirectUserToDiscoveryPage() +{ + $url = \Factory::getConfigService()->getServerBaseUrl(); + header("Location: " . $url); + die(); +} From 959c8339afa733b28f0008fbec061ee54ba8c990 Mon Sep 17 00:00:00 2001 From: Greg Corbett Date: Thu, 19 May 2022 13:52:40 +0000 Subject: [PATCH 2/6] Add support for EOSC IdPs out of the box - Use "voPersonID" to consume the user's identifier - The ePUID has been deprecated following the (AAI teams?) adoption of the AARC-G026 guidelines. --- .../AuthTokens/ShibAuthToken.php | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/lib/Authentication/AuthTokens/ShibAuthToken.php b/lib/Authentication/AuthTokens/ShibAuthToken.php index af6f9a9a2..ecfcdec44 100644 --- a/lib/Authentication/AuthTokens/ShibAuthToken.php +++ b/lib/Authentication/AuthTokens/ShibAuthToken.php @@ -79,11 +79,11 @@ public function getDetails() { public function getPrinciple() { return $this->principal; } - - - + + + private function getAttributesInitToken(){ - $hostname = $_SERVER['HTTP_HOST']; // don't use $_SERVER['SERVER_NAME'] as this don't support DNS + $hostname = $_SERVER['HTTP_HOST']; // don't use $_SERVER['SERVER_NAME'] as this don't support DNS // specify location of the Shib Logout handler \Factory::$properties['LOGOUTURL'] = 'https://'.$hostname.'/Shibboleth.sso/Logout'; $idp = isset($_SERVER['Shib-Identity-Provider']) ? $_SERVER['Shib-Identity-Provider'] : ''; @@ -152,8 +152,8 @@ private function getAttributesInitToken(){ } if(empty($_SERVER['entitlement'])){ die('Did not receive the required entitlement attribute from the EGI Dev Proxy IdP, please contact gocdb-admins'); - } - $entitlementValuesArray = explode(';', $_SERVER['entitlement']); + } + $entitlementValuesArray = explode(';', $_SERVER['entitlement']); if( !in_array('urn:mace:egi.eu:res:gocdb#aai.egi.eu', $entitlementValuesArray) ){ $HTML = ''; $HTML .= "
"; @@ -166,6 +166,46 @@ private function getAttributesInitToken(){ $this->userDetails = array('AuthenticationRealm' => array('EGI Proxy IdP')); return; } + else if($idp == 'https://aai-demo.eosc-portal.eu/proxy/saml2/idp/metadata.php'){ + if( empty($_SERVER['voPersonID'])){ + die('Did not receive required voPersonID attributes from the EOSC Demo Proxy Identity Provider to complete authentication, please contact gocdb-admins'); + } + if(empty($_SERVER['entitlement'])){ + die('Did not receive the required entitlement attribute from the EOSC Demo Proxy Identity Provider, please contact gocdb-admins'); + } + $entitlementValuesArray = explode(';', $_SERVER['entitlement']); + if( !in_array('urn:geant:eosc-portal.eu:res:gocdb.eosc-portal.eu#aai.eosc-portal.eu', $entitlementValuesArray) ){ + $HTML = '
  • You authenticated to the EOSC Demo Proxy Identity Provider using a method that does not provide a GOCDB entitlement.
  • Login is required with a GOCDB entitlement.
  • To gain access, you will need to login to the Proxy IdP using a scheme that provides a gocdb entitlement.
  • Please logout or restart your browser and attempt to login again.
'; + $HTML .= "
"; + $HTML .= 'Logout'; + $HTML .= "
"; + echo ($HTML); + die(); + } + $this->principal = $_SERVER['voPersonID']; + $this->userDetails = array('AuthenticationRealm' => array('EOSC Demo Proxy IdP')); + return; + } + else if($idp == 'https://aai.eosc-portal.eu/proxy/saml2/idp/metadata.php'){ + if( empty($_SERVER['voPersonID'])){ + die('Did not receive required voPersonID attributes from the EOSC Proxy Identity Provider to complete authentication, please contact gocdb-admins'); + } + if(empty($_SERVER['entitlement'])){ + die('Did not receive the required entitlement attribute from the EOSC Proxy Identity Provider, please contact gocdb-admins'); + } + $entitlementValuesArray = explode(';', $_SERVER['entitlement']); + if( !in_array('urn:geant:eosc-portal.eu:res:gocdb.eosc-portal.eu#aai.eosc-portal.eu', $entitlementValuesArray) ){ + $HTML = '
  • You authenticated to the EOSC Proxy Identity Provider using a method that does not provide a GOCDB entitlement.
  • Login is required with a GOCDB entitlement.
  • To gain access, you will need to login to the Proxy IdP using a scheme that provides a gocdb entitlement.
  • Please logout or restart your browser and attempt to login again.
'; + $HTML .= "
"; + $HTML .= 'Logout'; + $HTML .= "
"; + echo ($HTML); + die(); + } + $this->principal = $_SERVER['voPersonID']; + $this->userDetails = array('AuthenticationRealm' => array('EOSC Proxy IdP')); + return; + } } /** From 7d1db742e13125fbc0d7e19eb22210cb999c84a3 Mon Sep 17 00:00:00 2001 From: gregcorbett Date: Thu, 30 Jun 2022 14:42:39 +0000 Subject: [PATCH 3/6] Use new EOSC AAI entitlement to access GOCDB --- lib/Authentication/AuthTokens/ShibAuthToken.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Authentication/AuthTokens/ShibAuthToken.php b/lib/Authentication/AuthTokens/ShibAuthToken.php index ecfcdec44..727ca990e 100644 --- a/lib/Authentication/AuthTokens/ShibAuthToken.php +++ b/lib/Authentication/AuthTokens/ShibAuthToken.php @@ -174,7 +174,7 @@ private function getAttributesInitToken(){ die('Did not receive the required entitlement attribute from the EOSC Demo Proxy Identity Provider, please contact gocdb-admins'); } $entitlementValuesArray = explode(';', $_SERVER['entitlement']); - if( !in_array('urn:geant:eosc-portal.eu:res:gocdb.eosc-portal.eu#aai.eosc-portal.eu', $entitlementValuesArray) ){ + if( !in_array('urn:geant:eosc-portal.eu:res:gocdb.eosc-portal.eu', $entitlementValuesArray) ){ $HTML = '
  • You authenticated to the EOSC Demo Proxy Identity Provider using a method that does not provide a GOCDB entitlement.
  • Login is required with a GOCDB entitlement.
  • To gain access, you will need to login to the Proxy IdP using a scheme that provides a gocdb entitlement.
  • Please logout or restart your browser and attempt to login again.
'; $HTML .= "
"; $HTML .= 'Logout'; @@ -194,7 +194,7 @@ private function getAttributesInitToken(){ die('Did not receive the required entitlement attribute from the EOSC Proxy Identity Provider, please contact gocdb-admins'); } $entitlementValuesArray = explode(';', $_SERVER['entitlement']); - if( !in_array('urn:geant:eosc-portal.eu:res:gocdb.eosc-portal.eu#aai.eosc-portal.eu', $entitlementValuesArray) ){ + if( !in_array('urn:geant:eosc-portal.eu:res:gocdb.eosc-portal.eu', $entitlementValuesArray) ){ $HTML = '
  • You authenticated to the EOSC Proxy Identity Provider using a method that does not provide a GOCDB entitlement.
  • Login is required with a GOCDB entitlement.
  • To gain access, you will need to login to the Proxy IdP using a scheme that provides a gocdb entitlement.
  • Please logout or restart your browser and attempt to login again.
'; $HTML .= "
"; $HTML .= 'Logout'; From 1835d2fcf792463513c99b2e2a52020b2c886175 Mon Sep 17 00:00:00 2001 From: gregcorbett Date: Thu, 30 Jun 2022 15:06:56 +0000 Subject: [PATCH 4/6] Add EOSC AAI to getAuthTypes method - This is needed to determine a default ID string for a user --- lib/Gocdb_Services/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Gocdb_Services/User.php b/lib/Gocdb_Services/User.php index c926e8e7f..8cd06eb06 100644 --- a/lib/Gocdb_Services/User.php +++ b/lib/Gocdb_Services/User.php @@ -490,9 +490,9 @@ public function getAuthTypes($reducedRealms=true) { // Hardcoded authentication realms in same order as in token definitions $x509Realms = ['X.509']; if ($reducedRealms) { - $shibRealms = ['EGI Proxy IdP']; + $shibRealms = ['EGI Proxy IdP', 'EOSC Proxy IdP']; } else { - $shibRealms = ['EUDAT_SSO_IDP', 'UK_ACCESS_FED', 'EGI Proxy IdP']; + $shibRealms = ['EUDAT_SSO_IDP', 'UK_ACCESS_FED', 'EGI Proxy IdP', 'EOSC Proxy IdP']; } $irisRealms = ['IRIS IAM - OIDC']; From 3445be51ed02dc655c46dd65d15b9c00b8503cf1 Mon Sep 17 00:00:00 2001 From: gregcorbett Date: Thu, 30 Jun 2022 15:18:05 +0000 Subject: [PATCH 5/6] Remove check that auth type is valid. - MyConfig1.php should be the source of what AuthTokens/Types are valid. --- lib/Gocdb_Services/User.php | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/Gocdb_Services/User.php b/lib/Gocdb_Services/User.php index 8cd06eb06..f46156600 100644 --- a/lib/Gocdb_Services/User.php +++ b/lib/Gocdb_Services/User.php @@ -721,9 +721,6 @@ protected function addUserIdentifierValidation($keyName, $keyValue) { // Check the ID string does not already exist $this->valdidateUniqueIdString($keyValue); - - // Check auth type is valid - $this->valdidateAuthType($keyName); } /** @@ -808,9 +805,6 @@ protected function editUserIdentifierValidation(\User $user, \UserIdentifier $id $this->valdidateUniqueIdString($keyValue); } - // Check auth type is valid - $this->valdidateAuthType($keyName); - // If the identifiers key has changed, check there isn't an existing identifier with that key if ($keyName !== $identifier->getKeyName()) { $existingIdentifiers = $user->getUserIdentifiers(); @@ -822,17 +816,6 @@ protected function editUserIdentifierValidation(\User $user, \UserIdentifier $id } } - /** - * Validate authentication type based on known list. - * @param string $authType - * @throws \Exception - */ - protected function valdidateAuthType($authType) { - if (!in_array($authType, $this->getAuthTypes(false))) { - throw new \Exception("The authentication type entered is invalid"); - } - } - /** * Validate ID string is unique. * Checks both user identifiers and certificateDns From 653e379192d773a4523515515a759878de62a745 Mon Sep 17 00:00:00 2001 From: gregcorbett Date: Thu, 30 Jun 2022 15:42:13 +0000 Subject: [PATCH 6/6] Expose EOSC AAI ID strings via API --- lib/Gocdb_Services/PI/GetNGIContacts.php | 3 ++- lib/Gocdb_Services/PI/GetProjectContacts.php | 3 ++- lib/Gocdb_Services/PI/GetServiceGroupRole.php | 3 ++- lib/Gocdb_Services/PI/GetSiteContacts.php | 3 ++- lib/Gocdb_Services/PI/GetUser.php | 1 + 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/Gocdb_Services/PI/GetNGIContacts.php b/lib/Gocdb_Services/PI/GetNGIContacts.php index b094791c3..ed0fdb410 100644 --- a/lib/Gocdb_Services/PI/GetNGIContacts.php +++ b/lib/Gocdb_Services/PI/GetNGIContacts.php @@ -285,6 +285,7 @@ private function getXML(){ $xmlContact->addChild('CERTDN', $serv->getIdStringByAuthType($user, 'X.509')); $xmlContact->addChild('EGICHECKIN', $serv->getIdStringByAuthType($user, 'EGI Proxy IdP')); $xmlContact->addChild('IRISIAM', $serv->getIdStringByAuthType($user, 'IRIS IAM - OIDC')); + $xmlContact->addChild('EOSCAAI', $serv->getIdStringByAuthType($user, 'EOSC Proxy IdP')); } else { $xmlContact->addChild('CERTDN', $serv->getDefaultIdString($user)); } @@ -359,4 +360,4 @@ public function getPostExecutionPageInfo(){ $pageInfo['count'] = $this->resultSetSize; return $pageInfo; } -} \ No newline at end of file +} diff --git a/lib/Gocdb_Services/PI/GetProjectContacts.php b/lib/Gocdb_Services/PI/GetProjectContacts.php index 9b3e1e191..61165a032 100644 --- a/lib/Gocdb_Services/PI/GetProjectContacts.php +++ b/lib/Gocdb_Services/PI/GetProjectContacts.php @@ -264,6 +264,7 @@ private function getXML(){ $xmlContact->addChild('CERTDN', $serv->getIdStringByAuthType($user, 'X.509')); $xmlContact->addChild('EGICHECKIN', $serv->getIdStringByAuthType($user, 'EGI Proxy IdP')); $xmlContact->addChild('IRISIAM', $serv->getIdStringByAuthType($user, 'IRIS IAM - OIDC')); + $xmlContact->addChild('EOSCAAI', $serv->getIdStringByAuthType($user, 'EOSC Proxy IdP')); } else { $xmlContact->addChild('CERTDN', $serv->getDefaultIdString($user)); } @@ -339,4 +340,4 @@ public function getPostExecutionPageInfo(){ $pageInfo['count'] = $this->resultSetSize; return $pageInfo; } -} \ No newline at end of file +} diff --git a/lib/Gocdb_Services/PI/GetServiceGroupRole.php b/lib/Gocdb_Services/PI/GetServiceGroupRole.php index 807815537..a80fef2fb 100644 --- a/lib/Gocdb_Services/PI/GetServiceGroupRole.php +++ b/lib/Gocdb_Services/PI/GetServiceGroupRole.php @@ -299,6 +299,7 @@ private function getXML(){ $xmlUser->addChild ( 'CERTDN', $serv->getIdStringByAuthType ( $user, 'X.509' ) ); $xmlUser->addChild ( 'EGICHECKIN', $serv->getIdStringByAuthType ( $user, 'EGI Proxy IdP' ) ); $xmlUser->addChild ( 'IRISIAM', $serv->getIdStringByAuthType ( $user, 'IRIS IAM - OIDC' ) ); + $xmlUser->addChild('EOSCAAI', $serv->getIdStringByAuthType($user, 'EOSC Proxy IdP')); } else { $xmlUser->addChild ( 'CERTDN', $serv->getDefaultIdString ( $user ) ); } @@ -374,4 +375,4 @@ public function getPostExecutionPageInfo(){ $pageInfo['count'] = $this->resultSetSize; return $pageInfo; } -} \ No newline at end of file +} diff --git a/lib/Gocdb_Services/PI/GetSiteContacts.php b/lib/Gocdb_Services/PI/GetSiteContacts.php index 429e684b8..8648aac6a 100644 --- a/lib/Gocdb_Services/PI/GetSiteContacts.php +++ b/lib/Gocdb_Services/PI/GetSiteContacts.php @@ -315,6 +315,7 @@ private function getXML(){ $xmlContact->addChild ( 'CERTDN', $serv->getIdStringByAuthType ( $user, 'X.509' ) ); $xmlContact->addChild ( 'EGICHECKIN', $serv->getIdStringByAuthType ( $user, 'EGI Proxy IdP' ) ); $xmlContact->addChild ( 'IRISIAM', $serv->getIdStringByAuthType ( $user, 'IRIS IAM - OIDC' ) ); + $xmlContact->addChild('EOSCAAI', $serv->getIdStringByAuthType($user, 'EOSC Proxy IdP')); } else { $xmlContact->addChild ( 'CERTDN', $serv->getDefaultIdString ( $user ) ); } @@ -388,4 +389,4 @@ public function getPostExecutionPageInfo(){ $pageInfo['count'] = $this->resultSetSize; return $pageInfo; } -} \ No newline at end of file +} diff --git a/lib/Gocdb_Services/PI/GetUser.php b/lib/Gocdb_Services/PI/GetUser.php index 3e0ab0adb..59c6c3e3d 100644 --- a/lib/Gocdb_Services/PI/GetUser.php +++ b/lib/Gocdb_Services/PI/GetUser.php @@ -306,6 +306,7 @@ private function getXML() { $xmlUser->addChild('CERTDN', $serv->getIdStringByAuthType($user, 'X.509')); $xmlUser->addChild('EGICHECKIN', $serv->getIdStringByAuthType($user, 'EGI Proxy IdP')); $xmlUser->addChild('IRISIAM', $serv->getIdStringByAuthType($user, 'IRIS IAM - OIDC')); + $xmlUser->addChild('EOSCAAI', $serv->getIdStringByAuthType($user, 'EOSC Proxy IdP')); } else { $xmlUser->addChild('CERTDN', $serv->getDefaultIdString($user)); }