diff --git a/config/gocdb_schema.xml b/config/gocdb_schema.xml index 089ae632b..9f087392d 100644 --- a/config/gocdb_schema.xml +++ b/config/gocdb_schema.xml @@ -583,7 +583,7 @@ TYPE 255 - /^X509$/ + /^(X509|OIDC Subject)$/ diff --git a/htdocs/PI/index.php b/htdocs/PI/index.php index 34e5471d0..4027de40c 100644 --- a/htdocs/PI/index.php +++ b/htdocs/PI/index.php @@ -369,8 +369,8 @@ function getXml() { function authAnyCert() { if (empty($this->dn)) - die("Welcome to GOCDB

Use of GOCDB is governed by the EGI Acceptable Use Policy which places restrictions on your use of the service.

The GOCDB Privacy Notice describes what personal data is collected and why, and your rights regarding this data.

Please read these documents before accessing GOCDB.

- Access GOCDB + +
+ Access GOCDB using your IGTF X.509 Certificate +

or

+

Access GOCDB using one of the following:

+
+ + EGI Check-In + IRIS IAM +

Browse the GOCDB documentation index on the EGI wiki.

diff --git a/htdocs/web_portal/components/Get_User_Principle.php b/htdocs/web_portal/components/Get_User_Principle.php index 15af58eca..efbc20fe2 100644 --- a/htdocs/web_portal/components/Get_User_Principle.php +++ b/htdocs/web_portal/components/Get_User_Principle.php @@ -162,21 +162,29 @@ function Get_User_Principle(){ } /** - * Get the DN from an x509 cert or null if a user certificate can't be loaded. - * Called from the PI to authenticate requests using certificates only. + * Get the DN from an x509 cert, Principle from oidc token, or null if neither can be loaded. + * Called from the PI to authenticate requests using certificates or oidc. * @return string or null if can't authenticate request */ function Get_User_Principle_PI() { $fwMan = \org\gocdb\security\authentication\FirewallComponentManager::getInstance(); $firewallArray = $fwMan->getFirewallArray(); - try { + try{ $x509Token = new org\gocdb\security\authentication\X509AuthenticationToken(); $auth = $firewallArray['fwC1']->authenticate($x509Token); return $auth->getPrinciple(); } catch(org\gocdb\security\authentication\AuthenticationException $ex){ + // failed auth, so attempt OIDC auth + try{ + $token = new org\gocdb\security\authentication\IAMAuthToken(); + $auth = $firewallArray['fwC1']->authenticate($token); + return $auth->getPrinciple(); + } catch(org\gocdb\security\authentication\AuthenticationException $ex){ // failed auth, so return null and let calling page decide to allow // access or not (some PI methods don't need to be authenticated with a cert) + } } + return null; } diff --git a/htdocs/web_portal/controllers/site/add_api_auth.php b/htdocs/web_portal/controllers/site/add_api_auth.php index bbf7cadaa..1dd9b51b9 100644 --- a/htdocs/web_portal/controllers/site/add_api_auth.php +++ b/htdocs/web_portal/controllers/site/add_api_auth.php @@ -59,6 +59,7 @@ function draw(\User $user = null, \Site $site = null) { $params['site'] = $site; $params['authTypes'] = array(); $params['authTypes'][]='X509'; + $params['authTypes'][]='OIDC Subject'; show_view("site/add_api_auth.php", $params); die(); diff --git a/htdocs/web_portal/controllers/site/edit_api_auth.php b/htdocs/web_portal/controllers/site/edit_api_auth.php index 772c70120..3120cca85 100644 --- a/htdocs/web_portal/controllers/site/edit_api_auth.php +++ b/htdocs/web_portal/controllers/site/edit_api_auth.php @@ -61,6 +61,7 @@ function draw(\User $user = null, \APIAuthentication $authEnt = null, \Site $sit $params['authEnt'] = $authEnt; $params['authTypes'] = array(); $params['authTypes'][]='X509'; + $params['authTypes'][]='OIDC Subject'; show_view("site/edit_api_auth.php", $params); die(); diff --git a/htdocs/web_portal/controllers/user/register.php b/htdocs/web_portal/controllers/user/register.php index 97e2902c4..6c76ba73d 100644 --- a/htdocs/web_portal/controllers/user/register.php +++ b/htdocs/web_portal/controllers/user/register.php @@ -56,10 +56,20 @@ function draw() { die(); } + //Extract users email from oidc claims + $authDetails = $_SERVER['OIDC_CLAIM_external_authn']; + $startPos = 3+strpos($authDetails, ":", (strpos($authDetails, "MAIL"))); + $endPos = strpos($authDetails, "\"", 3+$startPos); + $length = $endPos-$startPos; + $userEmail = substr($authDetails, $startPos, $length); + /* @var $authToken \org\gocdb\security\authentication\IAuthentication */ $authToken = Get_User_AuthToken(); $params['authAttributes'] = $authToken->getDetails(); + $params['given_name'] = $_SERVER['OIDC_CLAIM_given_name']; + $params['family_name'] = $_SERVER['OIDC_CLAIM_family_name']; + $params['email'] = $userEmail; $params['dn'] = $dn; show_view('user/register.php', $params); } @@ -91,4 +101,4 @@ function submit() { } } -?> \ No newline at end of file +?> diff --git a/htdocs/web_portal/views/site/add_api_auth.php b/htdocs/web_portal/views/site/add_api_auth.php index 063d8e344..005e710ac 100644 --- a/htdocs/web_portal/views/site/add_api_auth.php +++ b/htdocs/web_portal/views/site/add_api_auth.php @@ -4,7 +4,7 @@ Caution: it is possible to delete information using the write functionality of the API.
- Identifier (e.g. Certificate DN)* + Identifier (e.g. Certificate DN or OIDC Subject)*
Credential type* diff --git a/htdocs/web_portal/views/site/edit_api_auth.php b/htdocs/web_portal/views/site/edit_api_auth.php index 284bae1fe..f30848efb 100644 --- a/htdocs/web_portal/views/site/edit_api_auth.php +++ b/htdocs/web_portal/views/site/edit_api_auth.php @@ -2,7 +2,7 @@

Edit API credential for getName());?>


- Identifier (e.g. Certificate DN)* + Identifier (e.g. Certificate DN or OIDC Subject)*
Credential type* diff --git a/htdocs/web_portal/views/user/register.php b/htdocs/web_portal/views/user/register.php index e6d063267..4a730b47b 100644 --- a/htdocs/web_portal/views/user/register.php +++ b/htdocs/web_portal/views/user/register.php @@ -56,19 +56,19 @@ Forename * (unaccentuated letters, spaces, dashes and quotes) - + Surname * (unaccentuated letters, spaces, dashes and quotes) - + E-Mail * (valid e-mail format) - + Telephone Number diff --git a/lib/Authentication/AuthProviders/GOCDBAuthProvider.php b/lib/Authentication/AuthProviders/GOCDBAuthProvider.php index 19a953f53..d67cb7c73 100644 --- a/lib/Authentication/AuthProviders/GOCDBAuthProvider.php +++ b/lib/Authentication/AuthProviders/GOCDBAuthProvider.php @@ -43,6 +43,9 @@ public function authenticate(IAuthentication $auth){ else if($auth instanceof SimpleSamlPhpAuthToken){ $roles[] = 'ROLE_SAMLUSER'; } + else if($auth instanceof IAMAuthToken){ + $roles[] = 'ROLE_IRISUSER'; + } $auth->setAuthorities($roles); return $auth; } diff --git a/lib/Authentication/AuthTokens/IAMAuthToken.php b/lib/Authentication/AuthTokens/IAMAuthToken.php new file mode 100644 index 000000000..4bdceb572 --- /dev/null +++ b/lib/Authentication/AuthTokens/IAMAuthToken.php @@ -0,0 +1,132 @@ +getAttributesInitToken(); + } + + /** + * {@see IAuthentication::eraseCredentials()} + */ + public function eraseCredentials() { + + } + + /** + * {@see IAuthentication::getAuthorities()} + */ + public function getAuthorities() { + return $this->authorities; + } + + /** + * {@see IAuthentication::getCredentials()} + * @return string An empty string as passwords are not used by this token. + */ + public function getCredentials() { + return ""; // none used in this token, handled by SSO/SAML + } + + /** + * A custom object used to store additional user details. + * Allows non-security related user information (such as email addresses, + * telephone numbers etc) to be stored in a convenient location. + * {@see IAuthentication::getDetails()} + * + * @return Object or null if not used + */ + public function getDetails() { + return $this->userDetails; + } + + /** + * {@see IAuthentication::getPrinciple()} + * @return string unique principle string of user + */ + public function getPrinciple() { + return $this->principal; + } + + + + private function getAttributesInitToken(){ + if(isset($_SERVER['OIDC_access_token'])){ + $this->principal = $_SERVER["REMOTE_USER"]; + $this->userDetails = array('AuthenticationRealm' => array('IRIS IAM - OIDC')); + //Don't allow access if user only has a local account on IRIS + if(strpos($_SERVER['OIDC_CLAIM_groups'], "localAccounts")===false){ + }else{ + die('You must login via your organisation on IRIS IAM to gain access to this site.'); + } + //Don't allow access unless user is a member of the IRIS gocdb group + if(strpos($_SERVER['OIDC_CLAIM_groups'], "gocdb")===false and in_array('gocdb', $_SERVER['OIDC_CLAIM_groups'])===false){ + die('You do not belong to the correct group to gain access to this site. Please visit iris-iam.stfc.ac.uk and submit a request to join the GOCDB group. This shall be reviewed by a GOCDB admin.'); + } + } + } + + /** + * {@see IAuthentication::setAuthorities($authorities)} + */ + public function setAuthorities($authorities) { + $this->authorities = $authorities; + } + + /** + * {@see IAuthentication::setDetails($userDetails)} + * @param Object $userDetails + */ + public function setDetails($userDetails) { + $this->userDetails = $userDetails; + } + + /** + * {@see IAuthentication::validate()} + */ + public function validate() { + + } + + /** + * {@see IAuthentication::isPreAuthenticating()} + */ + public static function isPreAuthenticating() { + return true; + } + + /** + * Returns true, this token reads the ShibSP session attributes and so + * does not need to be stateful itself. + * {@see IAuthentication::isStateless()} + */ + public static function isStateless() { + return true; + } + +} diff --git a/lib/Authentication/AuthTokens/ShibAuthToken.php b/lib/Authentication/AuthTokens/ShibAuthToken.php index db9d364b4..af6f9a9a2 100644 --- a/lib/Authentication/AuthTokens/ShibAuthToken.php +++ b/lib/Authentication/AuthTokens/ShibAuthToken.php @@ -166,15 +166,6 @@ private function getAttributesInitToken(){ $this->userDetails = array('AuthenticationRealm' => array('EGI Proxy IdP')); return; } - - -// else { -// die('Now go configure this AuthToken file ['.__FILE__.']'); -// } - // if we have not set the principle/userDetails, re-direct to our Discovery Service - $target = urlencode("https://" . $hostname . "/portal/"); - header("Location: https://" . $hostname . "/Shibboleth.sso/Login?target=" . $target); - die(); } /** diff --git a/lib/Authentication/MyConfig1.php b/lib/Authentication/MyConfig1.php index 7a1f2ecf3..5054c41dd 100644 --- a/lib/Authentication/MyConfig1.php +++ b/lib/Authentication/MyConfig1.php @@ -35,6 +35,7 @@ function __construct() { $this->tokenClassList = array(); $this->tokenClassList[] = 'org\gocdb\security\authentication\X509AuthenticationToken'; + //$this->tokenClassList[] = 'org\gocdb\security\authentication\IAMAuthToken'; $this->tokenClassList[] = 'org\gocdb\security\authentication\ShibAuthToken'; //$this->tokenClassList[] = 'org\gocdb\security\authentication\SimpleSamlPhpAuthToken'; //$this->tokenClassList[] = 'org\gocdb\security\authentication\UsernamePasswordAuthenticationToken'; diff --git a/lib/Gocdb_Services/Site.php b/lib/Gocdb_Services/Site.php index 85efe8e8f..9086eb6ec 100644 --- a/lib/Gocdb_Services/Site.php +++ b/lib/Gocdb_Services/Site.php @@ -1408,6 +1408,11 @@ public function addAPIAuthEntity(\Site $site, \User $user, $newValues) { if ($type == 'X509' && !preg_match("/^(\/[A-Za-z]+=[a-zA-Z0-9\/\-\_\s\.,'@:\/]+)*$/", $identifier)) { throw new \Exception("Invalid x509 DN"); } + + //If the entity is of type OIDC subject, do a more thorough check again + if ($type == 'OIDC Subject' && !preg_match("/^([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})$/", $identifier)) { + throw new \Exception("Invalid OIDC Subject"); + } //Check there isn't already a identifier of that type with that identifier for that Site $this->uniqueAPIAuthEnt($site, $identifier, $type); @@ -1488,6 +1493,11 @@ public function editAPIAuthEntity(\APIAuthentication $authEntity, \User $user, $ throw new \Exception("Invalid x509 DN"); } + //If the entity is of type OIDC subject, do a more thorough check again + if ($type == 'OIDC Subject' && !preg_match("/^([a-z0-9]{8}\-[a-z0-9]{4}\-[a-z0-9]{4}\-[a-z0-9]{4}\-[a-z0-9]{12})$/", $identifier)) { + throw new \Exception("Invalid OIDC Subject"); + } + /** * As long as something has changed, check there isn't already a * identifier of that type with that identifier for that Site