diff --git a/classes/CallbackHandler.php b/classes/CallbackHandler.php index de88c9e88153c36c0a043f7fc93d6954a3387a8c..85d33e978b8c3d128ab6fe642a5751dedee85f9a 100644 --- a/classes/CallbackHandler.php +++ b/classes/CallbackHandler.php @@ -48,13 +48,13 @@ class CallbackHandler { public static function manageLoginRedirect($user) { - global $BASE_PATH, $session; + global $BASE_PATH, $session, $log; - if (isset($session->callback) && $session->callback !== null) { + if ($session->getCallbackURL() !== null) { // External login using token $token = Util::createNewToken(); - DAO::get()->insertTokenData($token, $user->id); - header('Location: ' . $session->callback . '?token=' . $token); + DAO::get()->createLoginToken($token, $user->id); + header('Location: ' . $session->getCallbackURL() . '?token=' . $token); } else { // Login in session $session->user = $user; diff --git a/classes/DAO.php b/classes/DAO.php index 8a9d0789f7eb5fa76b2d669f0b6bcdb2ae96bfaf..713eff90539f3f46ba8add7d430c68ffb797cb68 100644 --- a/classes/DAO.php +++ b/classes/DAO.php @@ -60,11 +60,13 @@ abstract class DAO { public abstract function createJoinRequest($token, $applicantUserId, $targetUserId); - public $config; + public abstract function findJoinRequest($token); - public function __construct($config) { - $this->config = $config; - } + public abstract function deleteUser($userId); + + public abstract function joinUsers($userId1, $userId2); + + public abstract function deleteJoinRequest($token); public static function get() { global $DATABASE; diff --git a/classes/GrouperClient.php b/classes/GrouperClient.php new file mode 100644 index 0000000000000000000000000000000000000000..2bef66b38c7c04ee42eec2b85b52f6809dd33e8e --- /dev/null +++ b/classes/GrouperClient.php @@ -0,0 +1,110 @@ +<?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. + */ + +namespace RAP; + +class GrouperClient { + + private $client; + + function __construct($config) { + + $this->client = new \SoapClient($config['wsdlURL'], array( + 'login' => $config['user'], + 'password' => $config['password'], + 'trace' => 1, + // See: https://bugs.php.net/bug.php?id=36226 + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS + ) + ); + } + + private function getBaseRequestParams() { + return array( + 'clientVersion' => 'v2_3_000' + ); + } + + private function startsWith($haystack, $needle) { + return strpos($haystack, "$needle", 0) === 0; + } + + private function isSuccess($response) { + $success = isset($response->return->resultMetadata) && $response->return->resultMetadata->resultCode === 'SUCCESS'; + if (!$success) { + throw new \Exception("Web Service Failure. Response=" . json_encode($response)); + } + return $success; + } + + public function getSubjectGroups($subjectId) { + + $params = $this->getBaseRequestParams(); + $params['subjectLookups'] = array( + 'subjectId' => $subjectId, + 'subjectSourceId' => 'RAP' + ); + + $response = $this->client->getGroups($params); + + if ($this->isSuccess($response)) { + if (count($response->return->results) === 1) { + $groups = []; + foreach ($response->return->results[0]->wsGroups as $group) { + if (!$this->startsWith($group->name, 'etc:')) { + array_push($groups, $group->name); + } + } + return $groups; + } else { + throw new \Exception("Wrong results number. Response=" . json_encode($response)); + } + } + } + + public function addMemberships($subjectId, $groups) { + + foreach ($groups as $group) { + $params = $this->getBaseRequestParams(); + $params['subjectId'] = $subjectId; + $params['subjectSourceId'] = 'RAP'; + $params['groupName'] = $group; + + $this->client->addMemberLite($params); + } + } + + public function removeMemberships($subjectId, $groups) { + + foreach ($groups as $group) { + $params = $this->getBaseRequestParams(); + $params['subjectId'] = $subjectId; + $params['subjectSourceId'] = 'RAP'; + $params['groupName'] = $group; + + $this->client->deleteMemberLite($params); + } + } + +} diff --git a/classes/TokenHandler.php b/classes/MailSender.php similarity index 70% rename from classes/TokenHandler.php rename to classes/MailSender.php index 4c7998ade71c855226a52c1a943644c5f50a347f..cede88a89c79eac54a6a0460884206e0bf49d2f0 100644 --- a/classes/TokenHandler.php +++ b/classes/MailSender.php @@ -24,20 +24,10 @@ namespace RAP; -class TokenHandler { +class MailSender { - public static function createNewToken($data) { - $token = bin2hex(openssl_random_pseudo_bytes(16)); // http://stackoverflow.com/a/18890309/771431 - DAO::get()->insertTokenData($token, $data); - return $token; - } - - public static function deleteToken($token) { - DAO::get()->deleteToken($token); - } - - public static function getUserData($token) { - return DAO::get()->findTokenData($token); + public static function sendJoinEmail(User $recipientUser, User $applicantUser) { + } } diff --git a/classes/MySQLDAO.php b/classes/MySQLDAO.php index 05ba51a75a2afb6d38ec3656612934d49c4bb650..ab2cddb174984eb907bf2a7aa2cfeac62cbd4614 100644 --- a/classes/MySQLDAO.php +++ b/classes/MySQLDAO.php @@ -29,8 +29,12 @@ use PDO; class MySQLDAO extends DAO { public function getDBHandler() { - $connectionString = "mysql:host=" . $this->config['hostname'] . ";dbname=" . $this->config['dbname']; - return new PDO($connectionString, $this->config['username'], $this->config['password']); + global $DATABASE; + $connectionString = "mysql:host=" . $DATABASE['hostname'] . ";dbname=" . $DATABASE['dbname']; + $dbh = new PDO($connectionString, $DATABASE['username'], $DATABASE['password']); + // For transaction errors (see https://stackoverflow.com/a/9659366/771431) + $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + return $dbh; } public function createLoginToken($token, $userId) { @@ -130,6 +134,10 @@ class MySQLDAO extends DAO { public function findUserById($userId) { + if (!filter_var($userId, FILTER_VALIDATE_INT)) { + return null; + } + $dbh = $this->getDBHandler(); $stmt = $dbh->prepare("SELECT `id`, `type`, `typed_id`, `email`, `local_db_id`, `name`, `surname`, `institution`, `username`, `eppn`" @@ -269,4 +277,75 @@ class MySQLDAO extends DAO { $stmt->execute(); } + public function findJoinRequest($token) { + $dbh = $this->getDBHandler(); + + $stmt = $dbh->prepare("SELECT `applicant_user_id`, `target_user_id` FROM `join_request` WHERE `token` = :token"); + $stmt->bindParam(':token', $token); + $stmt->execute(); + + $result = $stmt->fetchAll(); + + switch (count($result)) { + case 0: + return null; + case 1: + $row = $result[0]; + return [$row['applicant_user_id'], $row['target_user_id']]; + default: + throw new Exception("Found multiple join request with the same token"); + } + } + + public function deleteUser($userId) { + $dbh = $this->getDBHandler(); + + $stmt3 = $dbh->prepare("DELETE FROM TABLE `user` WHERE `id` = :id2"); + $stmt3->bindParam(':id2', $userId); + $stmt3->execute(); + } + + public function joinUsers($userId1, $userId2) { + $dbh = $this->getDBHandler(); + + try { + $dbh->beginTransaction(); + + // Moving identities from user2 to user1 + $stmt1 = $dbh->prepare("UPDATE `identity` SET `user_id` = :id1 WHERE `user_id` = :id2"); + $stmt1->bindParam(':id1', $userId1); + $stmt1->bindParam(':id2', $userId2); + $stmt1->execute(); + + // Moving additional email addresses from user2 to user1 + $stmt2 = $dbh->prepare("UPDATE `additional_email` SET `user_id` = :id1 WHERE `user_id` = :id2"); + $stmt2->bindParam(':id1', $userId1); + $stmt2->bindParam(':id2', $userId2); + $stmt2->execute(); + + // Deleting user2 join requests + $stmt3 = $dbh->prepare("DELETE FROM `join_request` WHERE `target_user_id` = :id2"); + $stmt3->bindParam(':id2', $userId2); + $stmt3->execute(); + + // Deleting user2 + $stmt4 = $dbh->prepare("DELETE FROM `user` WHERE `id` = :id2"); + $stmt4->bindParam(':id2', $userId2); + $stmt4->execute(); + + $dbh->commit(); + } catch (Exception $ex) { + $dbh->rollBack(); + throw $ex; + } + } + + public function deleteJoinRequest($token) { + $dbh = $this->getDBHandler(); + + $stmt = $dbh->prepare("DELETE FROM `join_request` WHERE `token` = :token"); + $stmt->bindParam(':token', $token); + $stmt->execute(); + } + } diff --git a/classes/User.php b/classes/User.php index 220c6f088c4a28f7e851ff708f712f072e37d2c3..1d7a6cb9b9250637224eb8c4d3b4a357b38d7cef 100644 --- a/classes/User.php +++ b/classes/User.php @@ -43,4 +43,7 @@ class User { array_push($this->additionalEmailAddresses, $email); } + public function getPrimaryEmail() { + return $this->identities[0]->email; + } } diff --git a/classes/UserHandler.php b/classes/UserHandler.php index bb3bb3eceb9efa616702bcfb4682df5e08a233ba..27223bb3fbc760e1d8484e052e0897696d940eab 100644 --- a/classes/UserHandler.php +++ b/classes/UserHandler.php @@ -52,4 +52,19 @@ class UserHandler { return DAO::get()->findUserByIdentity($type, $identifier, $dbIdentifier); } + public static function joinUsers($userId1, $userId2) { + + global $GROUPER; + + if (isset($GROUPER)) { + $gc = new GrouperClient($GROUPER); + + $groupsToMove = $gc->getSubjectGroups('RAP:' . $userId2); + $gc->addMemberships('RAP:' . $userId1, $groupsToMove); + $gc->removeMemberships('RAP:' . $userId2, $groupsToMove); + } + + DAO::get()->joinUsers($userId1, $userId2); + } + } diff --git a/classes/UserSearchResult.php b/classes/UserSearchResult.php index daada02ea3d19caadf4e04cd3b6c512c74454640..25de1ad65ea0494889ed1603c57fc5c9c27cbfd6 100644 --- a/classes/UserSearchResult.php +++ b/classes/UserSearchResult.php @@ -26,12 +26,12 @@ namespace RAP; class UserSearchResult { - private $userId; + private $user; public $userDisplayText; public static function buildFromUser(User $user) { $usr = new UserSearchResult(); - $usr->userId = $user->id; + $usr->user = $user; $nameAndSurname = null; $email = null; @@ -71,8 +71,8 @@ class UserSearchResult { return $usr; } - public function getUserId() { - return $this->userId; + public function getUser() { + return $this->user; } } diff --git a/classes/X509Data.php b/classes/X509Data.php new file mode 100644 index 0000000000000000000000000000000000000000..c907452c094a4f783e2c6470cbd4880f04a23f44 --- /dev/null +++ b/classes/X509Data.php @@ -0,0 +1,148 @@ +<?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. + */ + +namespace RAP; + +class X509Data { + + public $email; + public $fullName; + public $institution; + public $serialNumber; + + /** + * Retrieve full name from CN, removing the e-mail if necessary + */ + private function parseCN($cn) { + $cnSplit = explode(" ", $cn); + + $count = count($cnSplit); + $lastSegment = $cnSplit[$count - 1]; + + if (strpos($lastSegment, "@") === false) { + if ($count < 2) { + // We need name + surname + throw new \Exception("Unparsable CN"); + } + $this->fullName = $cn; + } else { + // Last segment is an email + if ($count < 3) { + // We need name + surname + email + throw new \Exception("Unparsable CN"); + } + + // Rebuilding full name removing the email part + $cnLength = strlen($cn); + $emailLength = strlen($lastSegment); + // -1 is for removing also the space between surname and email + $this->fullName = substr($cn, 0, $cnLength - $emailLength - 1); + } + } + + private function parseUsingOpenSSL($sslClientCert) { + + $parsedX509 = openssl_x509_parse($sslClientCert); + + // try extracting email + if (isset($parsedX509["extensions"]["subjectAltName"])) { + $AyAlt = explode(":", $parsedX509["extensions"]["subjectAltName"]); + if ($AyAlt[0] === "email") { + $this->email = $AyAlt[1]; + } + } + + $this->serialNumber = $parsedX509["serialNumber"]; + + $cn = $parsedX509["subject"]["CN"]; + $this->parseCN($cn); + + $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; + } + } + } + + public static function parse($server) { + + $parsedData = new X509Data(); + + if (isset($server['SSL_CLIENT_CERT'])) { + $parsedData->parseUsingOpenSSL(['SSL_CLIENT_CERT']); + // If all mandatory information has been parsed return the object + if ($parsedData->email !== null && $parsedData->fullName !== null && $parsedData->serialNumber !== null) { + return $parsedData; + } + } + + 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"); + } + } + + if ($parsedData->email === null) { + 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'])) { + // 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']; + // TODO + } else { + throw new Exception("Unable to retrieve serial number from certificate"); + } + } + + return $parsedData; + } + +} diff --git a/config.php b/config.php index 53d270460b050d208cb0bd061f6c7305b8ef6826..b29bb713eb6510684880fcd12af4297160b3ea8b 100644 --- a/config.php +++ b/config.php @@ -72,3 +72,10 @@ $AUTHENTICATION_METHODS = array( ) ) ); + +$GROUPER = array( + //'serviceBaseURL' => 'https://sso.ia2.inaf.it/grouper-ws/servicesRest', + 'wsdlURL' => 'http://localhost:8087/grouper-ws/services/GrouperService_v2_3?wsdl', + 'user' => 'GrouperSystem', + 'password' => '***REMOVED***' +); diff --git a/css/style.css b/css/style.css index f44bc67f44b4bf00b74b952b30650633980f908d..f76e0fa5c0b4dcda79337c71b3593d90e619a635 100644 --- a/css/style.css +++ b/css/style.css @@ -103,7 +103,7 @@ body { margin-bottom: 8px } -.callback-title { +.page-title { margin-top: 0; font-weight: bold; color: #24388e; @@ -121,3 +121,24 @@ body { .panel-default > .panel-heading { background-image: linear-gradient(to bottom,#f5f5f5 0,#ccc 100%); } + +.table-like { + display: table; + width: 100%; +} + +.table-like .table-row { + display: table-row; +} + +.table-row .table-cell { + display: table-cell; + vertical-align: middle; +} + +.join-icon-cell { + min-width: 100px; + text-align: center; + font-size: 30px; +} + diff --git a/include/front-controller.php b/include/front-controller.php index 28c26903c7951c8e86a48fd96d0a407d14ed5f90..7ad325abcf2c337dc533476f9ed01cac95a1815a 100644 --- a/include/front-controller.php +++ b/include/front-controller.php @@ -37,3 +37,67 @@ Flight::route('/facebook', function() { startSession(); Flight::redirect('/oauth2/facebook_login.php'); }); + +Flight::route('/eduGAIN', function() { + startSession(); + Flight::redirect('/saml2/aai.php'); +}); + +Flight::route('/x509', function() { + startSession(); + Flight::redirect('/x509/certlogin.php'); +}); + +Flight::route('GET /confirm-join', function() { + $token = Flight::request()->query['token']; + + if ($token === null) { + http_response_code(422); + die("Token not found"); + } + + $dao = RAP\DAO::get(); + + $userIds = $dao->findJoinRequest($token); + if ($userIds === null) { + http_response_code(422); + die("Invalid token"); + } + + $applicantUser = $dao->findUserById($userIds[0]); + $targetUser = $dao->findUserById($userIds[1]); + + Flight::render('confirm-join.php', array('title' => 'RAP', + 'token' => $token, + 'applicantUser' => $applicantUser, + 'targetUser' => $targetUser)); +}); + +Flight::route('POST /confirm-join', function() { + + $token = Flight::request()->data['token']; + + if ($token === null) { + http_response_code(422); + die("Token not found"); + } + + $dao = RAP\DAO::get(); + + $userIds = $dao->findJoinRequest($token); + if ($userIds === null) { + http_response_code(422); + die("Invalid token"); + } + + RAP\UserHandler::joinUsers($userIds[0], $userIds[1]); + $dao->deleteJoinRequest($token); + + // Force user to relogin to see changes to him/her identities + session_start(); + session_destroy(); + + global $BASE_PATH; + Flight::render('join-success.php', array('title' => 'Success - RAP Join Request', + 'basePath' => $BASE_PATH)); +}); diff --git a/include/gui-backend.php b/include/gui-backend.php index 6087bb3277fd8abaf3529aa0d07c55c3b658e518..2506bbbb735495d2fe3c157cf97f72900900863d 100644 --- a/include/gui-backend.php +++ b/include/gui-backend.php @@ -38,10 +38,12 @@ Flight::route('POST /join', function() { global $session; $selectedUserIndex = Flight::request()->data['selectedUserIndex']; - $targetUserId = $session->userSearchResults[$selectedUserIndex]->getUserId(); + $selectedSearchResult = $session->userSearchResults[$selectedUserIndex]; + $targetUserId = $selectedSearchResult->getUser()->id; $token = RAP\Util::createNewToken(); RAP\DAO::get()->createJoinRequest($token, $session->user->id, $targetUserId); + RAP\MailSender::sendJoinEmail($selectedSearchResult->getUser(), $session->user); - echo ""; + echo $selectedSearchResult->userDisplayText; }); diff --git a/include/init.php b/include/init.php index cfb824c825299a2ea4d47908c6fb0517ffa4a0c7..f74e1e30936f67149c51f66441eae2dc70e761c5 100644 --- a/include/init.php +++ b/include/init.php @@ -34,9 +34,12 @@ spl_autoload_register(function ($class_name) { } }); +// Loading dependecy classes include ROOT . '/vendor/autoload.php'; +// Loading configuration include ROOT . '/config.php'; +// Setup logging $log = new Monolog\Logger('mainLogger'); $log->pushHandler(new Monolog\Handler\StreamHandler($LOG_PATH, $LOG_LEVEL)); diff --git a/include/rest-web-service.php b/include/rest-web-service.php index e913e8a70c73feb2bfd76d9f780e3e7e4102439f..2eca4f1a0dc0194785daa851b242d21475030ab3 100644 --- a/include/rest-web-service.php +++ b/include/rest-web-service.php @@ -9,14 +9,14 @@ $WS_PREFIX = '/ws'; Flight::route('GET ' . $WS_PREFIX . '/user-info', function() { $token = Flight::request()->query['token']; - $userData = RAP\DAO::get()->findTokenData($token); + $userData = RAP\DAO::get()->findLoginToken($token); if (is_null($userData)) { http_response_code(404); die("Token not found"); } - RAP\DAO::get()->deleteToken($token); + RAP\DAO::get()->deleteLoginToken($token); header('Content-Type: text/plain'); echo $userData; @@ -40,3 +40,6 @@ Flight::route('GET ' . $WS_PREFIX . '/user', function() { $users = RAP\DAO::get()->searchUser($searchText); echo json_encode($users); }); + +Flight::route('GET ' . $WS_PREFIX . '/test', function() { +}); diff --git a/include/user-data.php b/include/user-data.php new file mode 100644 index 0000000000000000000000000000000000000000..755cfcd9acfa5a483f55604cdd0af9041263a6fa --- /dev/null +++ b/include/user-data.php @@ -0,0 +1,28 @@ +<?php foreach ($user->identities as $identity) { ?> + <dl class="dl-horizontal"> + <dt>Type</dt> + <dd><?php echo $identity->type; ?></dd> + <dt>E-mail</dt> + <dd><?php echo $identity->email; ?></dd> + <?php if ($identity->eppn !== null) { ?> + <dt>EduPersonPrincipalName</dt> + <dd><?php echo $identity->eppn; ?></dd> + <?php } ?> + <?php if ($identity->username !== null) { ?> + <dt>Username</dt> + <dd><?php echo $identity->username; ?></dd> + <?php } ?> + <?php if ($identity->name !== null) { ?> + <dt>Name</dt> + <dd><?php echo $identity->name; ?></dd> + <?php } ?> + <?php if ($identity->surname !== null) { ?> + <dt>Surname</dt> + <dd><?php echo $identity->surname; ?></dd> + <?php } ?> + <?php if ($identity->institution !== null) { ?> + <dt>Institution</dt> + <dd><?php echo $identity->institution; ?></dd> + <?php } ?> + </dl> +<?php } ?> diff --git a/js/script.js b/js/script.js index 2ee30793e57f581b539ac38f219a31fc289db004..bc1a24912f0b0cf0963f036dafa5204d193bf5ac 100644 --- a/js/script.js +++ b/js/script.js @@ -20,11 +20,16 @@ } function sendJoinRequest() { + $userSelector = $('#user-selector-group select'); var selectedUserIndex = $userSelector.val(); + if (selectedUserIndex !== null) { $.post('join', {selectedUserIndex: selectedUserIndex}, function (response) { - console.log(response); + $('#search-user-modal').modal('hide'); + $infoAlert = $('#info-message-alert'); + $infoAlert.find('.info-message').text("An e-mail has been sent to " + response + " primary e-mail address."); + $infoAlert.removeClass('hide'); }); } } @@ -43,6 +48,10 @@ // Add click event handler to join request button $(document).on('click', '#send-join-request-btn', sendJoinRequest); + + $(document).on('click', '#info-message-alert .close', function () { + $('#info-message-alert').addClass('hide'); + }); }); })(jQuery); \ No newline at end of file diff --git a/saml2/aai.php b/saml2/aai.php new file mode 100644 index 0000000000000000000000000000000000000000..ff23b16b8e14287341a5619072017bf7d6ecadda --- /dev/null +++ b/saml2/aai.php @@ -0,0 +1,52 @@ +<?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['Shib-Session-ID'])) { + + $eppn = $_SERVER['eppn']; + + $user = RAP\UserHandler::findUserByIdentity(RAP\Identity::EDU_GAIN, $eppn, null); + + if ($user === null) { + $user = new RAP\User(); + + $identity = new RAP\Identity(RAP\Identity::EDU_GAIN); + $identity->email = $_SERVER['mail']; + $identity->name = $_SERVER['givenName']; + $identity->surname = $_SERVER['sn']; + $identity->typedId = $eppn; + //$_SERVER['Shib-Identity-Provider'] + + $user->addIdentity($identity); + + RAP\UserHandler::saveUser($user); + } + + RAP\CallbackHandler::manageLoginRedirect($user); +} else { + throw new Exception("Shib-Session-ID not found!"); +} diff --git a/views/confirm-join.php b/views/confirm-join.php new file mode 100644 index 0000000000000000000000000000000000000000..60ef13782a4f7d2a4dbec215895f46f8ee2a15e3 --- /dev/null +++ b/views/confirm-join.php @@ -0,0 +1,47 @@ +<?php +include 'include/header.php'; +?> + +<h1 class="text-center page-title">Confirm join request</h1> + +<br/> +<div class="table-like"> + <div class="table-row"> + <div class="table-cell"> + <div class="panel panel-default"> + <div class="panel-body"> + <?php + $user = $applicantUser; + include 'include/user-data.php'; + ?> + </div> + </div> + </div> + <div class="table-cell join-icon-cell text-success"> + <span class="glyphicon glyphicon-transfer"></span> + </div> + <div class="table-cell"> + <div class="panel panel-default"> + <div class="panel-body"> + <?php + $user = $targetUser; + include 'include/user-data.php'; + ?> + </div> + </div> + </div> + </div> +</div> + +<div class="row"> + <div class="col-xs-12 text-center"> + <p>Pressing the following button the identities listed below will be joined.</p> + <form action="confirm-join" method="POST"> + <input type="hidden" name="token" value="<?php echo $token; ?>" /> + <input type="submit" class="btn btn-success btn-lg" value="Join users" /> + </form> + </div> +</div> + +<?php +include 'include/footer.php'; diff --git a/views/index.php b/views/index.php index 5a27057e4d0140edb905b53fd92886f2dd0b1ff9..e7eb9f06a9f7057681625e83b693213b223c40b5 100644 --- a/views/index.php +++ b/views/index.php @@ -5,7 +5,7 @@ include 'include/header.php'; <?php if ($session->user === null) { ?> <div class="row"> <div class="col-xs-12"> - <h1 class="text-center callback-title"><?php echo $session->getCallbackTitle(); ?></h1> + <h1 class="text-center page-title"><?php echo $session->getCallbackTitle(); ?></h1> </div> </div> <div class="row"> @@ -71,6 +71,15 @@ include 'include/header.php'; </div> </div> <?php } else { ?> + <div class="row"> + <div class="col-xs-12"> + <div class="alert alert-success hide" id="info-message-alert"> + <button type="button" class="close" aria-label="Close"><span aria-hidden="true">×</span></button> + <span class="glyphicon glyphicon-info-sign"></span> + <span class="info-message"></span> + </div> + </div> + </div> <div class="row"> <div class="col-sm-5 col-xs-12"> <div class="panel panel-default"> @@ -78,34 +87,10 @@ include 'include/header.php'; <h3 class="panel-title">Your identities</h3> </div> <div class="panel-body"> - <?php foreach ($session->user->identities as $identity) { ?> - <dl class="dl-horizontal"> - <dt>Type</dt> - <dd><?php echo $identity->type; ?></dd> - <dt>E-mail</dt> - <dd><?php echo $identity->email; ?></dd> - <?php if ($identity->eppn !== null) { ?> - <dt>EduPersonPrincipalName</dt> - <dd><?php echo $identity->eppn; ?></dd> - <?php } ?> - <?php if ($identity->username !== null) { ?> - <dt>Username</dt> - <dd><?php echo $identity->username; ?></dd> - <?php } ?> - <?php if ($identity->name !== null) { ?> - <dt>Name</dt> - <dd><?php echo $identity->name; ?></dd> - <?php } ?> - <?php if ($identity->surname !== null) { ?> - <dt>Surname</dt> - <dd><?php echo $identity->surname; ?></dd> - <?php } ?> - <?php if ($identity->institution !== null) { ?> - <dt>Institution</dt> - <dd><?php echo $identity->institution; ?></dd> - <?php } ?> - </dl> - <?php } ?> + <?php + $user = $session->user; + include 'include/user-data.php'; + ?> </div> </div> </div> diff --git a/views/join-success.php b/views/join-success.php new file mode 100644 index 0000000000000000000000000000000000000000..0587bd0cf79f5df8a4d8d6f405584d17b75d7460 --- /dev/null +++ b/views/join-success.php @@ -0,0 +1,15 @@ +<?php +include 'include/header.php'; +?> + +<h1 class="text-center page-title">Success</h1> + +<br/> +<div class="text-center"> + <p>Your identities have been joined!</p> + <br/> + <p><a href="<?php echo $basePath; ?>">Return to index</a></p> +</div> + +<?php +include 'include/footer.php'; diff --git a/x509/certlogin.php b/x509/certlogin.php new file mode 100644 index 0000000000000000000000000000000000000000..1694ecff4558c966cc434ac5a37b215f7af3602f --- /dev/null +++ b/x509/certlogin.php @@ -0,0 +1,49 @@ +<?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']; + } +}