diff --git a/.htaccess b/.htaccess index a936070078e11dd48efdda9c4f5eb1d1fb9d6c32..0654970d0361d0925f2a271bf72101b1c16784c9 100644 --- a/.htaccess +++ b/.htaccess @@ -1,3 +1,4 @@ +Options -Indexes RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d diff --git a/README.md b/README.md index 9591a34744d6c9bbe4a9af7f0d2130707f974119..99cf896e6bcc09502d53100f30415da85bded2fc 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ For installing PHP dependencies run: composer install +Install also the bcmath PHP package (used in X.509 parser). + To setup the database edit scripts in the sql folder and run them: mysql -u root -p < sql/create-db-and-user.sql diff --git a/oauth2/facebook_login.php b/auth/oauth2/facebook_login.php similarity index 97% rename from oauth2/facebook_login.php rename to auth/oauth2/facebook_login.php index e89404eddf27bfb84feb2b8b447be209348b4060..e6d59870a30602330fb5c82222bf88f889163354 100755 --- a/oauth2/facebook_login.php +++ b/auth/oauth2/facebook_login.php @@ -22,7 +22,7 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -include '../include/init.php'; +include '../../include/init.php'; startSession(); $Facebook = $AUTHENTICATION_METHODS['Facebook']; diff --git a/oauth2/facebook_token.php b/auth/oauth2/facebook_token.php similarity index 98% rename from oauth2/facebook_token.php rename to auth/oauth2/facebook_token.php index 7e05a14fc6a7f4c0c482f6d9e2b4220076683c24..1daca05bde24a7711f9191d52f55dfdb5fa4f5e0 100755 --- a/oauth2/facebook_token.php +++ b/auth/oauth2/facebook_token.php @@ -22,7 +22,7 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -include '../include/init.php'; +include '../../include/init.php'; startSession(); $Facebook = $AUTHENTICATION_METHODS['Facebook']; @@ -80,7 +80,7 @@ $fbUser = $response->getGraphUser(); $typedId = $fbUser["id"]; -$user = RAP\UserHandler::findUserByIdentity(RAP\Identity::FACEBOOK, $typedId, null); +$user = RAP\UserHandler::findUserByIdentity(RAP\Identity::FACEBOOK, $typedId); if ($user === null) { $user = new RAP\User(); diff --git a/oauth2/google_token.php b/auth/oauth2/google_token.php similarity index 98% rename from oauth2/google_token.php rename to auth/oauth2/google_token.php index 990ee84b9e76584665fb101b5f9342033808c364..59e9c014873c9ec099805eb38846a0b2ef91bdb5 100644 --- a/oauth2/google_token.php +++ b/auth/oauth2/google_token.php @@ -22,7 +22,7 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -include '../include/init.php'; +include '../../include/init.php'; startSession(); $Google = $AUTHENTICATION_METHODS['Google']; @@ -74,7 +74,7 @@ if ($client->getAccessToken()) { $typedId = explode('/', $res->getResourceName())[1]; - $user = RAP\UserHandler::findUserByIdentity(RAP\Identity::GOOGLE, $typedId, null); + $user = RAP\UserHandler::findUserByIdentity(RAP\Identity::GOOGLE, $typedId); if ($user === null) { $user = new RAP\User(); diff --git a/saml2/aai.php b/auth/saml2/aai.php similarity index 93% rename from saml2/aai.php rename to auth/saml2/aai.php index ff23b16b8e14287341a5619072017bf7d6ecadda..02a728d79af0c585b2c8e5d00ef4a45fb5d5faa0 100644 --- a/saml2/aai.php +++ b/auth/saml2/aai.php @@ -22,14 +22,14 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -include '../include/init.php'; +include '../../include/init.php'; startSession(); if (isset($_SERVER['Shib-Session-ID'])) { $eppn = $_SERVER['eppn']; - $user = RAP\UserHandler::findUserByIdentity(RAP\Identity::EDU_GAIN, $eppn, null); + $user = RAP\UserHandler::findUserByIdentity(RAP\Identity::EDU_GAIN, $eppn); if ($user === null) { $user = new RAP\User(); @@ -48,5 +48,6 @@ if (isset($_SERVER['Shib-Session-ID'])) { RAP\CallbackHandler::manageLoginRedirect($user); } else { - throw new Exception("Shib-Session-ID not found!"); + http_response_code(500); + die("Shib-Session-ID not found!"); } diff --git a/auth/x509/certlogin.php b/auth/x509/certlogin.php new file mode 100644 index 0000000000000000000000000000000000000000..e2319ea6ad1dc425e51cd6f74727526668d716e1 --- /dev/null +++ b/auth/x509/certlogin.php @@ -0,0 +1,80 @@ +<?php + +/* ---------------------------------------------------------------------------- + * INAF - National Institute for Astrophysics + * IRA - Radioastronomical Institute - Bologna + * OATS - Astronomical Observatory - Trieste + * ---------------------------------------------------------------------------- + * + * Copyright (C) 2016 Istituto Nazionale di Astrofisica + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License Version 3 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +include '../../include/init.php'; +startSession(); + +function saveUserFromX509Data($x509Data) { + + global $session; + + $user = new RAP\User(); + + $identity = new RAP\Identity(RAP\Identity::X509); + $identity->email = $x509Data->email; + $identity->name = $x509Data->name; + $identity->surname = $x509Data->surname; + $identity->typedId = $x509Data->serialNumber; + $identity->institution = $x509Data->institution; + + $user->addIdentity($identity); + + RAP\UserHandler::saveUser($user); + + $session->x509DataToRegister = null; + + return $user; +} + +if ($session->x509DataToRegister !== null && $session->x509DataToRegister->name !== null) { + + $user = saveUserFromX509Data($session->x509DataToRegister); +} else { + + if (isset($_SERVER['SSL_CLIENT_VERIFY']) && isset($_SERVER['SSL_CLIENT_V_REMAIN']) && + $_SERVER['SSL_CLIENT_VERIFY'] === 'SUCCESS' && $_SERVER['SSL_CLIENT_V_REMAIN'] > 0) { + + $x509Data = RAP\X509Data::parse($_SERVER); + + $user = RAP\UserHandler::findUserByIdentity(RAP\Identity::X509, $x509Data->serialNumber); + + if ($user === null) { + + if ($x509Data->name === null) { + $session->x509DataToRegister = $x509Data; + $session->save(); + header('Location: ' . $BASE_PATH . '/x509-name-surname'); + die(); + } else { + $user = saveUserFromX509Data($x509Data); + } + } + } else { + http_response_code(500); + die("Unable to verify client certificate"); + } +} + +RAP\CallbackHandler::manageLoginRedirect($user); diff --git a/classes/DAO.php b/classes/DAO.php index 713eff90539f3f46ba8add7d430c68ffb797cb68..888f66c71e0a754c3f92a9f7eead4a7b58b1679c 100644 --- a/classes/DAO.php +++ b/classes/DAO.php @@ -50,9 +50,8 @@ abstract class DAO { * Return a User object, null if nothing was found. * @param type $type Identity type (EDU_GAIN, X509, GOOGLE, ...) * @param type $identifier value used to search the identity in the database - * @param type $dbIdentifier identifier of the database (used only for local identities) */ - public abstract function findUserByIdentity($type, $identifier, $dbIdentifier); + public abstract function findUserByIdentity($type, $identifier); public abstract function searchUser($searchText); diff --git a/classes/Identity.php b/classes/Identity.php index c611494dd7b1472c1bc755a70fe127c1adc159e2..e731aaba914c59c2300944b24c0af8778cc59596 100644 --- a/classes/Identity.php +++ b/classes/Identity.php @@ -56,11 +56,6 @@ class Identity { */ public $email; - /** - * Unique identifier for local user database (specified in configuration file). - */ - public $localDBId; - /** * First name */ @@ -76,11 +71,6 @@ class Identity { */ public $institution; - /** - * For local identities. - */ - public $username; - /** * For eduGAIN identities. */ diff --git a/classes/MySQLDAO.php b/classes/MySQLDAO.php index ab2cddb174984eb907bf2a7aa2cfeac62cbd4614..d6343b2bcba89d101b566fb8dd0a44cb4a8b632d 100644 --- a/classes/MySQLDAO.php +++ b/classes/MySQLDAO.php @@ -42,11 +42,11 @@ class MySQLDAO extends DAO { global $log; $dbh = $this->getDBHandler(); - $stmt = $dbh->prepare("INSERT INTO login_token (token, data) VALUES(:token, :data)"); + $stmt = $dbh->prepare("INSERT INTO login_token (token, user_id) VALUES(:token, :user_id)"); $params = array( ':token' => $token, - ':data' => $userId + ':user_id' => $userId ); if ($stmt->execute($params)) { @@ -61,13 +61,13 @@ class MySQLDAO extends DAO { $dbh = $this->getDBHandler(); - $stmt = $dbh->prepare("SELECT data FROM login_token WHERE token = :token AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE,1,creation_time)"); + $stmt = $dbh->prepare("SELECT user_id FROM login_token WHERE token = :token AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE,1,creation_time)"); $stmt->bindParam(':token', $token); $stmt->execute(); foreach ($stmt->fetchAll() as $row) { - return $row['data']; + return $row['user_id']; } return null; @@ -86,8 +86,8 @@ class MySQLDAO extends DAO { $dbh = $this->getDBHandler(); - $stmt = $dbh->prepare("INSERT INTO identity(`user_id`, `type`, `email`, `name`, `surname`, `institution`, `username`, `local_db_id`, `typed_id`, `eppn`)" - . " VALUES(:user_id, :type, :email, :name, :surname, :institution, :username, :local_db_id, :typed_id, :eppn)"); + $stmt = $dbh->prepare("INSERT INTO identity(`user_id`, `type`, `email`, `name`, `surname`, `institution`, `typed_id`, `eppn`)" + . " VALUES(:user_id, :type, :email, :name, :surname, :institution, :typed_id, :eppn)"); $stmt->bindParam(':user_id', $userId); $stmt->bindParam(':type', $identity->type); @@ -95,8 +95,6 @@ class MySQLDAO extends DAO { $stmt->bindParam(':name', $identity->name); $stmt->bindParam(':surname', $identity->surname); $stmt->bindParam(':institution', $identity->institution); - $stmt->bindParam(':username', $identity->username); - $stmt->bindParam(':local_db_id', $identity->localDBId); $stmt->bindParam(':typed_id', $identity->typedId); $stmt->bindParam(':eppn', $identity->eppn); @@ -122,11 +120,9 @@ class MySQLDAO extends DAO { $identity->id = $row['id']; $identity->typedId = $row['typed_id']; $identity->email = $row['email']; - $identity->localDBId = $row['local_db_id']; $identity->name = $row['name']; $identity->surname = $row['surname']; $identity->institution = $row['institution']; - $identity->username = $row['username']; $identity->eppn = $row['eppn']; return $identity; @@ -140,7 +136,7 @@ class MySQLDAO extends DAO { $dbh = $this->getDBHandler(); - $stmt = $dbh->prepare("SELECT `id`, `type`, `typed_id`, `email`, `local_db_id`, `name`, `surname`, `institution`, `username`, `eppn`" + $stmt = $dbh->prepare("SELECT `id`, `type`, `typed_id`, `email`, `name`, `surname`, `institution`, `eppn`" . " FROM identity WHERE user_id = :user_id"); $stmt->bindParam(':user_id', $userId); @@ -169,29 +165,20 @@ class MySQLDAO extends DAO { return $user; } - public function findUserByIdentity($type, $identifier, $dbIdentifier) { + public function findUserByIdentity($type, $identifier) { $dbh = $this->getDBHandler(); $query = "SELECT user_id FROM identity WHERE type = :type AND typed_id = :typed_id"; - if (isset($dbIdentifier) && $dbIdentifier !== null) { - $query .= " AND local_db_id = :local_db_id"; - } $stmt = $dbh->prepare($query); $stmt->bindParam(':type', $type); $stmt->bindParam(':typed_id', $identifier); - if (isset($dbIdentifier) && $dbIdentifier !== null) { - $stmt->bindParam(':local_db_id', $dbIdentifier); - } $stmt->execute(); $result = $stmt->fetchAll(); - global $log; - $log->debug("count = " . count($result)); - if (count($result) === 0) { return null; } @@ -209,7 +196,7 @@ class MySQLDAO extends DAO { // TODO: Add additional email search... - $query = "SELECT `user_id`, `id`, `type`, `typed_id`, `email`, `local_db_id`, `name`, `surname`, `institution`, `username`, `eppn`" + $query = "SELECT `user_id`, `id`, `type`, `typed_id`, `email`, `name`, `surname`, `institution`, `eppn`" . " FROM identity WHERE `email` LIKE :email OR `name` LIKE :name OR `surname` LIKE :surname"; $stmt = $dbh->prepare($query); @@ -223,15 +210,9 @@ class MySQLDAO extends DAO { $userMap = array(); - //global $log; - //$log->debug('In searchUser'); - foreach ($stmt->fetchAll() as $row) { - //$log->debug($row['user_id']); - $identity = $this->getIdentityByRow($row); - //$log->debug(json_encode($identity)); $userId = $row['user_id']; if (array_key_exists($userId, $userMap)) { diff --git a/classes/SessionData.php b/classes/SessionData.php index b2a885ea5f9529bf29c597bf4f7af44010c84dfc..cc578f21031ade8cfaf4e26ee6242c5942830fe6 100644 --- a/classes/SessionData.php +++ b/classes/SessionData.php @@ -30,6 +30,7 @@ class SessionData { private $callbackTitle; public $user; public $userSearchResults; + public $x509DataToRegister; public function save() { $_SESSION['SessionData'] = $this; diff --git a/classes/UserHandler.php b/classes/UserHandler.php index 27223bb3fbc760e1d8484e052e0897696d940eab..58c046248fbd838b53953d33187f3237f5d36714 100644 --- a/classes/UserHandler.php +++ b/classes/UserHandler.php @@ -47,9 +47,9 @@ class UserHandler { } } - public static function findUserByIdentity($type, $identifier, $dbIdentifier) { + public static function findUserByIdentity($type, $identifier) { - return DAO::get()->findUserByIdentity($type, $identifier, $dbIdentifier); + return DAO::get()->findUserByIdentity($type, $identifier); } public static function joinUsers($userId1, $userId2) { diff --git a/classes/X509Data.php b/classes/X509Data.php index c907452c094a4f783e2c6470cbd4880f04a23f44..c1bb523d9c1ded4aa10b7c1cef60492efd0cbdcc 100644 --- a/classes/X509Data.php +++ b/classes/X509Data.php @@ -30,6 +30,9 @@ class X509Data { public $fullName; public $institution; public $serialNumber; + public $name; + public $surname; + public $candidateNames; /** * Retrieve full name from CN, removing the e-mail if necessary @@ -81,23 +84,45 @@ class X509Data { $this->institution = $parsedX509["subject"]["O"]; } - private function extractDNFields($dn) { - $dnSplit = explode(",", $dn); - - foreach ($dnSplit as $dnField) { - $pos = strpos($dnField, "="); - $key = substr($dnField, 0, $pos - 1); - $value = substr($dnField, $pos + 1, strlen($dnField) - 1); - switch ($key) { - case 'CN': - $this->parseCN($value); - break; - case 'O': - $this->institution = $value; + /** + * Credits: https://stackoverflow.com/a/1273535/771431 + */ + private static function bchexdec($hex) { + $dec = 0; + $len = strlen($hex); + for ($i = 1; $i <= $len; $i++) { + $dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i)))); + } + return $dec; + } + + private function fillNameAndSurnameOrCandidates() { + $nameSplit = explode(' ', $this->fullName); + + if (count($nameSplit) === 2) { + $this->name = $nameSplit[0]; + $this->surname = $nameSplit[1]; + } else { + $this->candidateNames = []; + for ($i = 1; $i < count($nameSplit); $i++) { + $candidateName = ""; + for ($j = 0; $j < $i; $j++) { + if ($j > 0) { + $candidateName .= ' '; + } + $candidateName .= $nameSplit[$j]; + } + $this->candidateNames[] = $candidateName; } } } + public function selectCandidateName($candidateNameIndex) { + $candidateName = $this->candidateNames[$candidateNameIndex]; + $this->name = $candidateName; + $this->surname = substr($this->fullName, strlen($candidateName) + 1); + } + public static function parse($server) { $parsedData = new X509Data(); @@ -113,35 +138,39 @@ class X509Data { if ($parsedData->fullName === null) { if (isset($server['SSL_CLIENT_S_DN_CN'])) { $parsedData->parseCN($server['SSL_CLIENT_S_DN_CN']); - if ($parsedData->fullName === null) { - throw new \Exception("Unable to extract CN from DN"); - } } else { - throw new \Exception("Unable to obtain DN from certificate"); + throw new \Exception("Unable to retrieve CN from certificate"); } } if ($parsedData->email === null) { - if (isset($_SERVER['SSL_CLIENT_SAN_Email_0'])) { - $parsedData->email = $_SERVER['SSL_CLIENT_SAN_Email_0']; + if (isset($server['SSL_CLIENT_SAN_Email_0'])) { + $parsedData->email = $server['SSL_CLIENT_SAN_Email_0']; } else { throw new \Exception("Unable to retrieve e-mail address from certificate"); } } if ($parsedData->serialNumber === null) { - if (isset($_SERVER['SSL_CLIENT_M_SERIAL'])) { + if (isset($server['SSL_CLIENT_M_SERIAL'])) { // In this server variable the serial number is stored into an HEX format, // while openssl_x509_parse function provides it in DEC format. // Here a hex->dec conversion is performed, in order to store the // serial number in a consistent format: - $hexSerial = $_SERVER['SSL_CLIENT_M_SERIAL']; + $hexSerial = $server['SSL_CLIENT_M_SERIAL']; // TODO + $parsedData->serialNumber = X509Data::bchexdec($hexSerial); } else { throw new Exception("Unable to retrieve serial number from certificate"); } } + if ($parsedData->institution === null && isset($server['SSL_CLIENT_S_DN_O'])) { + $parsedData->institution = $server['SSL_CLIENT_S_DN_O']; + } + + $parsedData->fillNameAndSurnameOrCandidates(); + return $parsedData; } diff --git a/config.php b/config.php index b29bb713eb6510684880fcd12af4297160b3ea8b..840befa7a49d356922dc238608aef6059e698396 100644 --- a/config.php +++ b/config.php @@ -52,25 +52,14 @@ $AUTHENTICATION_METHODS = array( 'Google' => array( 'id' => "***REMOVED***.apps.googleusercontent.com", 'secret' => "***REMOVED***", - 'callback' => $BASE_PATH . "/oauth2/google_token.php"), + 'callback' => $BASE_PATH . "/auth/oauth2/google_token.php"), 'Facebook' => array( 'id' => "***REMOVED***", 'secret' => "***REMOVED***", 'version' => "v2.2", - 'callback' => $BASE_PATH . "/oauth2/facebook_token.php"), + 'callback' => $BASE_PATH . "/auth/oauth2/facebook_token.php"), 'LinkedIn' => array(), 'X.509' => array(), - 'Direct' => array( - array( - 'name' => 'IA2', - 'label' => '', - 'logo' => 'ia2-logo-60x60.png', - 'description' => 'Use the IA2 logo if you have an IA2 account (provided by IA2 or self-registered)', - 'type' => 'ldap', - 'ldap_user_scope' => 'ou=custom_users,dc=oats,dc=inaf,dc=it', - 'ldap_user_id_field' => 'uid' - ) - ) ); $GROUPER = array( diff --git a/css/chosen.min.css b/css/chosen.min.css deleted file mode 100644 index a264b6d8797a223fa398fad195f07149c4d22088..0000000000000000000000000000000000000000 --- a/css/chosen.min.css +++ /dev/null @@ -1,3 +0,0 @@ -/* Chosen v1.7.0 | (c) 2011-2017 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ - -.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.chosen-container *{box-sizing:border-box}.chosen-container .chosen-drop{position:absolute;top:100%;z-index:1010;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15);clip:rect(0,0,0,0)}.chosen-container.chosen-with-drop .chosen-drop{clip:auto}.chosen-container a{cursor:pointer}.chosen-container .search-choice .group-name,.chosen-container .chosen-single .group-name{margin-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-weight:400;color:#999}.chosen-container .search-choice .group-name:after,.chosen-container .chosen-single .group-name:after{content:":";padding-left:2px;vertical-align:top}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:25px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:linear-gradient(#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:url(chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;clip:rect(0,0,0,0)}.chosen-container .chosen-results{color:#444;position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;word-wrap:break-word;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{color:#777;display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;margin:0;padding:0 5px;width:100%;height:auto;border:1px solid #aaa;background-color:#fff;background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:0;height:25px;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#999;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0;width:25px}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 5px 3px 0;padding:3px 20px 3px 5px;border:1px solid #aaa;max-width:100%;border-radius:3px;background-color:#eee;background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-size:100% 19px;background-repeat:repeat-x;background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice span{word-wrap:break-word}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;border-bottom-right-radius:0;border-bottom-left-radius:0;background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:0;background:transparent}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#222!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:0}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:url(chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi),only screen and (min-resolution:1.5dppx){.chosen-rtl .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-container-single .chosen-search input[type=text],.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span{background-image:url(chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}} \ No newline at end of file diff --git a/css/style.css b/css/style.css index f76e0fa5c0b4dcda79337c71b3593d90e619a635..9affc9a218da8eb85aadc4e0a952242850cdf9e6 100644 --- a/css/style.css +++ b/css/style.css @@ -14,10 +14,9 @@ body { } .home-box { - float: left; + display: inline-block; width: 240px; height: 165px; - padding: 2px; margin: 10px; border-radius: 15px; border: 1px solid #ccc; diff --git a/img/ia2-logo-60x60.png b/img/ia2-logo-60x60.png deleted file mode 100644 index f93ef2495577ed01ad2a5ac25578607dd9891670..0000000000000000000000000000000000000000 Binary files a/img/ia2-logo-60x60.png and /dev/null differ diff --git a/include/front-controller.php b/include/front-controller.php index 7ad325abcf2c337dc533476f9ed01cac95a1815a..8c334d7cbe48fe26f3a22f3f80287f4d8617a56a 100644 --- a/include/front-controller.php +++ b/include/front-controller.php @@ -30,22 +30,22 @@ Flight::route('GET /logout', function() { Flight::route('/google', function() { startSession(); - Flight::redirect('/oauth2/google_token.php'); + Flight::redirect('/auth/oauth2/google_token.php'); }); Flight::route('/facebook', function() { startSession(); - Flight::redirect('/oauth2/facebook_login.php'); + Flight::redirect('/auth/oauth2/facebook_login.php'); }); Flight::route('/eduGAIN', function() { startSession(); - Flight::redirect('/saml2/aai.php'); + Flight::redirect('/auth/saml2/aai.php'); }); Flight::route('/x509', function() { startSession(); - Flight::redirect('/x509/certlogin.php'); + Flight::redirect('/auth/x509/certlogin.php'); }); Flight::route('GET /confirm-join', function() { @@ -101,3 +101,31 @@ Flight::route('POST /confirm-join', function() { Flight::render('join-success.php', array('title' => 'Success - RAP Join Request', 'basePath' => $BASE_PATH)); }); + +Flight::route('GET /x509-name-surname', function() { + + startSession(); + global $session, $BASE_PATH; + + if ($session->x509DataToRegister !== null && $session->x509DataToRegister->name === null) { + Flight::render('x509-name-surname.php', array('title' => 'Select name and surname', + 'fullName' => $session->x509DataToRegister->fullName, + 'candidateNames' => $session->x509DataToRegister->candidateNames)); + } else { + // Redirect to index + header("Location: " . $BASE_PATH); + } +}); + +Flight::route('POST /submit-x509-name', function() { + + $selectedNameIndex = Flight::request()->data['selected-name']; + + startSession(); + global $session, $BASE_PATH; + + if ($session->x509DataToRegister !== null) { + $session->x509DataToRegister->selectCandidateName($selectedNameIndex); + header("Location: " . $BASE_PATH . '/x509'); + } +}); diff --git a/include/header.php b/include/header.php index 29356dd43f6fc35a546977657bbd11615e9c09d9..7413c9aa95ee9d648dadfdede27e9df3d6782e3c 100644 --- a/include/header.php +++ b/include/header.php @@ -8,7 +8,6 @@ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <link rel="stylesheet" href="css/style.css" /> - <script src="js/script.js"></script> </head> <body> <header id="main-header"> diff --git a/include/init.php b/include/init.php index f74e1e30936f67149c51f66441eae2dc70e761c5..086d512461d038c60f952177a096019f21803651 100644 --- a/include/init.php +++ b/include/init.php @@ -40,6 +40,8 @@ include ROOT . '/vendor/autoload.php'; include ROOT . '/config.php'; // Setup logging +// Monolog require timezone to be set +date_default_timezone_set("Europe/Rome"); $log = new Monolog\Logger('mainLogger'); $log->pushHandler(new Monolog\Handler\StreamHandler($LOG_PATH, $LOG_LEVEL)); diff --git a/js/script.js b/js/index.js similarity index 100% rename from js/script.js rename to js/index.js diff --git a/js/x509-name-surname.js b/js/x509-name-surname.js new file mode 100644 index 0000000000000000000000000000000000000000..fb1488295003e7ec0d0a05642fcb9d0e9fbcbff7 --- /dev/null +++ b/js/x509-name-surname.js @@ -0,0 +1,20 @@ +(function ($) { + + var _fullName; + window.initPage = function (fullName) { + _fullName = fullName; + }; + + function fillSurnameFromSelectedCandidateName() { + var selectedName = $('#name-selector option:selected').text().trim(); + var surname = _fullName.substring(selectedName.length + 1); + $('#surname-text').text(surname); + } + + // When the document is loaded + $(document).ready(function () { + $(document).on('change', '#name-selector', fillSurnameFromSelectedCandidateName); + fillSurnameFromSelectedCandidateName(); + }); + +})(jQuery); diff --git a/sql/setup-database.sql b/sql/setup-database.sql index cff418a55e4cf7dcf68b8d0132b2c94331104b7c..60bdc47858125b2832c28a9938c56e82ca392f96 100644 --- a/sql/setup-database.sql +++ b/sql/setup-database.sql @@ -12,8 +12,6 @@ CREATE TABLE `identity` ( `name` varchar(255) DEFAULT NULL, `surname` varchar(255) DEFAULT NULL, `institution` varchar(255) DEFAULT NULL, - `username` varchar(255) DEFAULT NULL, - `local_db_id` varchar(255) DEFAULT NULL, `eppn` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) @@ -30,7 +28,7 @@ CREATE TABLE `additional_email` ( CREATE TABLE `login_token` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `token` varchar(255) NOT NULL, - `data` text, + `user_id` text, `creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/views/index.php b/views/index.php index e7eb9f06a9f7057681625e83b693213b223c40b5..e5ba7470c53b1d9d79743b7d2b8150dd4219824e 100644 --- a/views/index.php +++ b/views/index.php @@ -1,6 +1,7 @@ <?php include 'include/header.php'; ?> +<script src="js/index.js"></script> <?php if ($session->user === null) { ?> <div class="row"> @@ -9,7 +10,7 @@ include 'include/header.php'; </div> </div> <div class="row"> - <div class="col-xs-12"> + <div class="col-xs-12 text-center"> <?php if (isset($auth['eduGAIN'])) { ?> <div class="home-box"> <div class="img-wrapper"> @@ -52,22 +53,6 @@ include 'include/header.php'; Use the X.509 Logo to Login with your personal certificate (IGTF and TERENA-TACAR, are allowed). </div> <?php } ?> - <?php - if (isset($auth['Direct'])) { - foreach ($auth['Direct'] as $directAuth) { - ?> - <div class="home-box"> - <div class="img-wrapper"> - <a href="#"> - <img src="img/<?php echo $directAuth['logo']; ?>" alt="" /> - </a> - </div> - <?php echo $directAuth['description']; ?> - </div> - <?php - } - } - ?> </div> </div> <?php } else { ?> diff --git a/views/x509-name-surname.php b/views/x509-name-surname.php new file mode 100644 index 0000000000000000000000000000000000000000..aa5f159e70efbb4fc81d87cd5cc7ae1b8847bfe6 --- /dev/null +++ b/views/x509-name-surname.php @@ -0,0 +1,48 @@ +<?php +include 'include/header.php'; +?> +<script src="js/x509-name-surname.js"></script> +<script>initPage('<?php echo $fullName; ?>');</script> + +<h1 class="text-center page-title">Name and surname selection</h1> + +<br/> +<div class="text-center"> + <p>Your name+surname is longer than 3 words. Please select the correct combination from the list below:</p> +</div> + +<form action="submit-x509-name" method="POST"> + <div class="row"> + <div class="col-md-6 col-md-offset-3"> + <table class="table"> + <thead> + <tr> + <th>Name</th> + <th>Surname</th> + </tr> + </thead> + <tbody> + <tr> + <td> + <select class="form-control" id="name-selector" name="selected-name"> + <?php for ($i = 0; $i < count($candidateNames); $i++) { ?> + <option value="<?php echo $i; ?>" <?php echo $i === 0 ? 'selected' : ''; ?>> + <?php echo $candidateNames[$i]; ?> + </option> + <?php } ?> + </select> + </td> + <td><span id="surname-text"></span></td> + </tr> + </tbody> + </table> + </div> + </div> + + <div class="text-center"> + <input class="btn btn-success" value="Confirm" type="submit" /> + </div> +</form> + +<?php +include 'include/footer.php'; diff --git a/x509/certlogin.php b/x509/certlogin.php deleted file mode 100644 index 1694ecff4558c966cc434ac5a37b215f7af3602f..0000000000000000000000000000000000000000 --- a/x509/certlogin.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* ---------------------------------------------------------------------------- - * INAF - National Institute for Astrophysics - * IRA - Radioastronomical Institute - Bologna - * OATS - Astronomical Observatory - Trieste - * ---------------------------------------------------------------------------- - * - * Copyright (C) 2016 Istituto Nazionale di Astrofisica - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License Version 3 as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -include '../include/init.php'; -startSession(); - -if (isset($_SERVER['SSL_CLIENT_VERIFY']) && isset($_SERVER['SSL_CLIENT_V_REMAIN']) && - $_SERVER['SSL_CLIENT_VERIFY'] === 'SUCCESS' && $_SERVER['SSL_CLIENT_V_REMAIN'] > 0) { - - $email = null; - - if (isset($_SERVER['SSL_CLIENT_CERT'])) { - - $MYx509 = openssl_x509_parse($_SERVER['SSL_CLIENT_CERT']); - - if (isset($MYx509["extensions"]["subjectAltName"])) { - $AyAlt = explode(":", $MYx509["extensions"]["subjectAltName"]); - if ($AyAlt[0] === "email") { - $email = $AyAlt[1]; - } - } - } - - if (isset($_SERVER['SSL_CLIENT_S_DN_CN'])) { - $fullName = $_SERVER['SSL_CLIENT_S_DN_CN']; - } -}