Skip to content
Snippets Groups Projects
Commit c749a87e authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Added LinkedIn, little fixes

parent 658238a2
No related branches found
No related tags found
No related merge requests found
<?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();
$LinkedIn = $AUTHENTICATION_METHODS['LinkedIn'];
$url = "https://www.linkedin.com/oauth/v2/authorization?response_type=code";
$url .= "&client_id=" . $LinkedIn['id'];
$url .= "&redirect_uri=" . $LinkedIn['callback'];
$url .= "&state=789654123";
$url .= "&scope=r_basicprofile r_emailaddress";
header("Location: $url");
?>
<?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();
$LinkedIn = $AUTHENTICATION_METHODS['LinkedIn'];
if (!isset($_REQUEST['code'])) {
die("Unable to get LinkedIn client code");
}
//create array of data to be posted to get AccessToken
$post_data = array(
'grant_type' => "authorization_code",
'code' => $_REQUEST['code'],
'redirect_uri' => $LinkedIn['callback'],
'client_id' => $LinkedIn['id'],
'client_secret' => $LinkedIn['secret']);
//traverse array and prepare data for posting (key1=value1)
foreach ($post_data as $key => $value) {
$post_items[] = $key . '=' . $value;
}
//create the final string to be posted
$post_string = implode('&', $post_items);
//create cURL connection
$conn1 = curl_init('https://www.linkedin.com/oauth/v2/accessToken');
//set options
curl_setopt($conn1, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($conn1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($conn1, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($conn1, CURLOPT_FOLLOWLOCATION, 1);
//set data to be posted
curl_setopt($conn1, CURLOPT_POSTFIELDS, $post_string);
//perform our request
$result1 = curl_exec($conn1);
if ($result1) {
$my_token = json_decode($result1, TRUE);
$access_token = $my_token['access_token'];
$expires_in = $my_token['expires_in'];
curl_close($conn1);
} else {
//show information regarding the error
$errorMessage = curl_errno($conn1) . "-";
$errorMessage = $errorMessage . curl_error($conn1);
curl_close($conn1);
die($errorMessage);
}
// Call to API
$conn2 = curl_init();
curl_setopt($conn2, CURLOPT_URL, "https://api.linkedin.com/v1/people/~:(first-name,last-name,email-address,id)?format=json");
curl_setopt($conn2, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer ' . $access_token
));
curl_setopt($conn2, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($conn2);
if ($result) {
$data = json_decode($result, TRUE);
curl_close($conn2);
if (isset($data['errorCode'])) {
$errorMessage = $data['message'];
die($errorMessage);
}
$typedId = $data['id'];
$user = $userHandler->findUserByIdentity(RAP\Identity::LINKEDIN, $typedId);
if ($user === null) {
$user = new RAP\User();
$identity = new RAP\Identity(RAP\Identity::LINKEDIN);
$identity->email = $data['emailAddress'];
$identity->name = $data['firstName'];
$identity->surname = $data['lastName'];
$identity->typedId = $typedId;
$user->addIdentity($identity);
$userHandler->saveUser($user);
}
$callbackHandler->manageLoginRedirect($user, $session);
} else {
//show information regarding the error
$errorMessage = curl_errno($conn2) . "-";
$errorMessage = $errorMessage . curl_error($conn2);
curl_close($conn2);
die($errorMessage);
}
?>
...@@ -39,7 +39,7 @@ class CallbackHandler { ...@@ -39,7 +39,7 @@ class CallbackHandler {
/** /**
* returns null if the callback URL is not listed in configuration file. * returns null if the callback URL is not listed in configuration file.
*/ */
public static function getCallbackTitle($callbackURL) { public function getCallbackTitle($callbackURL) {
if ($callbackURL === null) { if ($callbackURL === null) {
return "Account Management"; return "Account Management";
...@@ -58,16 +58,22 @@ class CallbackHandler { ...@@ -58,16 +58,22 @@ class CallbackHandler {
if ($session->getCallbackURL() !== null) { if ($session->getCallbackURL() !== null) {
// External login using token // External login using token
$token = Util::createNewToken(); header('Location: ' . $this->getLoginWithTokenURL($user->id, $session->getCallbackURL()));
$this->dao->createLoginToken($token, $user->id); die();
header('Location: ' . $session->getCallbackURL() . '?token=' . $token);
} else { } else {
// Login in session // Login in session
$session->user = $user; $session->user = $user;
$session->save(); $session->save();
// Return to index // Return to index
header('Location: ' . $this->basePath); header('Location: ' . $this->basePath);
die();
}
} }
public function getLoginWithTokenURL($userId, $callbackURL) {
$token = Util::createNewToken();
$this->dao->createLoginToken($token, $userId);
return $callbackURL . '?token=' . $token;
} }
} }
...@@ -26,8 +26,60 @@ namespace RAP; ...@@ -26,8 +26,60 @@ namespace RAP;
class MailSender { class MailSender {
public static function sendJoinEmail(User $recipientUser, User $applicantUser) { private $serverName;
private $basePath;
public function __construct($serverName, $basePath) {
$this->serverName = $serverName;
$this->basePath = $basePath;
}
public function sendJoinEmail(User $recipientUser, User $applicantUser, $token) {
$subject = "IA2 RAP: Join request";
$header = "From: noreply@" . $this->serverName . "\r\n";
$header .= "Content-Type: text/html; charset=UTF-8";
$confirmJoinURL = $this->basePath . '/confirm-join?token=' . $token;
$body = "Dear IA2 user,<br/><br/>";
$body .= "the following user requested to join your accounts on the "
. "<a href=\"https://sso.ia2.inaf.it/rap-ia2/\" target=\"blank_\">RAP facility</a>:<br/><br/>";
foreach ($applicantUser->identities as $identity) {
$body .= "<b>Type</b>: " . $identity->type . "<br/>";
if ($identity->name !== null) {
$body .= "<b>Name</b>: " . $identity->name . "<br/>";
}
if ($identity->surname !== null) {
$body .= "<b>Surname</b>: " . $identity->surname . "<br/>";
}
$body .= "<b>E-mail</b>: " . $identity->email . "<br/>";
if ($identity->eppn !== null) {
$body .= "<b>Eppn</b>: " . $identity->eppn . "<br/>";
}
if ($identity->institution !== null) {
$body .= "<b>Institution</b>: " . $identity->institution . "<br/>";
}
$body .= "<br/>";
}
$body .= "<br/>If you and this user are the same person click on the following link for joining your accounts:<br/>";
$body .= "<a href=\"$confirmJoinURL\" target=\"blank_\">$confirmJoinURL</a>";
$body .= "<br/><br/>Otherwise you can ignore this email<br/><br/>";
$body .= "<b>*** This is an automatically generated email, please do not reply to this message ***</b><br/>";
$body .= "If you need information please contact <a href=\"mailto:ia2@oats.inaf.it\">IA2 Staff</a>";
mail($recipientUser->getPrimaryEmail(), $subject, $body, $header);
} }
} }
...@@ -246,6 +246,10 @@ class MySQLDAO implements DAO { ...@@ -246,6 +246,10 @@ class MySQLDAO implements DAO {
public function createJoinRequest($token, $applicantUserId, $targetUserId) { public function createJoinRequest($token, $applicantUserId, $targetUserId) {
if($applicantUserId === $targetUserId) {
throw new \Exception("Invalid target user id");
}
$dbh = $this->getDBHandler(); $dbh = $this->getDBHandler();
$stmt = $dbh->prepare("INSERT INTO `join_request`(`token`, `applicant_user_id`, `target_user_id`)" $stmt = $dbh->prepare("INSERT INTO `join_request`(`token`, `applicant_user_id`, `target_user_id`)"
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
$CONTEXT_ROOT = "/rap-service"; $CONTEXT_ROOT = "/rap-ia2";
$VERSION = "1.0.0"; $VERSION = "1.0.0";
$PROTOCOL = stripos($_SERVER['SERVER_PROTOCOL'], 'https') ? 'https://' : 'http://'; $PROTOCOL = stripos($_SERVER['SERVER_PROTOCOL'], 'https') ? 'https://' : 'http://';
...@@ -58,12 +58,15 @@ $AUTHENTICATION_METHODS = array( ...@@ -58,12 +58,15 @@ $AUTHENTICATION_METHODS = array(
'secret' => "***REMOVED***", 'secret' => "***REMOVED***",
'version' => "v2.2", 'version' => "v2.2",
'callback' => $BASE_PATH . "/auth/oauth2/facebook_token.php"), 'callback' => $BASE_PATH . "/auth/oauth2/facebook_token.php"),
'LinkedIn' => array(), 'LinkedIn' => array(
'id' => '***REMOVED***',
'secret' => '***REMOVED***',
'callback' => $BASE_PATH . '/auth/oauth2/linkedin_token.php'
),
'X.509' => array(), 'X.509' => array(),
); );
$GROUPER = array( $GROUPER = array(
//'serviceBaseURL' => 'https://sso.ia2.inaf.it/grouper-ws/servicesRest',
'wsdlURL' => 'http://localhost:8087/grouper-ws/services/GrouperService_v2_3?wsdl', 'wsdlURL' => 'http://localhost:8087/grouper-ws/services/GrouperService_v2_3?wsdl',
'user' => 'GrouperSystem', 'user' => 'GrouperSystem',
'password' => '***REMOVED***' 'password' => '***REMOVED***'
......
...@@ -12,14 +12,20 @@ function setCallback() { ...@@ -12,14 +12,20 @@ function setCallback() {
$callback = Flight::request()->data['callback']; $callback = Flight::request()->data['callback'];
$session->setCallbackURL($callbackHandler, isset($callback) ? $callback : null); $session->setCallbackURL($callbackHandler, isset($callback) ? $callback : null);
return $session->getCallbackURL();
} }
Flight::route('/', function() { Flight::route('/', function() {
startSession(); startSession();
setCallback(); $callback = setCallback();
global $session, $AUTHENTICATION_METHODS; global $session, $callbackHandler, $AUTHENTICATION_METHODS;
if ($callback !== null && $session->user !== null) {
$redirectURL = $callbackHandler->getLoginWithTokenURL($session->user->id, $callback);
Flight::redirect($redirectURL);
} else {
Flight::render('index.php', array('title' => 'RAP', Flight::render('index.php', array('title' => 'RAP',
'session' => $session, 'auth' => $AUTHENTICATION_METHODS)); 'session' => $session, 'auth' => $AUTHENTICATION_METHODS));
}
}); });
Flight::route('GET /logout', function() { Flight::route('GET /logout', function() {
...@@ -38,6 +44,11 @@ Flight::route('/facebook', function() { ...@@ -38,6 +44,11 @@ Flight::route('/facebook', function() {
Flight::redirect('/auth/oauth2/facebook_login.php'); Flight::redirect('/auth/oauth2/facebook_login.php');
}); });
Flight::route('/linkedIn', function() {
startSession();
Flight::redirect('/auth/oauth2/linkedin_login.php');
});
Flight::route('/eduGAIN', function() { Flight::route('/eduGAIN', function() {
startSession(); startSession();
Flight::redirect('/auth/saml2/aai.php'); Flight::redirect('/auth/saml2/aai.php');
......
...@@ -35,7 +35,7 @@ Flight::route('GET /user', function() { ...@@ -35,7 +35,7 @@ Flight::route('GET /user', function() {
Flight::route('POST /join', function() { Flight::route('POST /join', function() {
checkSession(); checkSession();
global $session, $dao; global $session, $dao, $mailSender;
$selectedUserIndex = Flight::request()->data['selectedUserIndex']; $selectedUserIndex = Flight::request()->data['selectedUserIndex'];
$selectedSearchResult = $session->userSearchResults[$selectedUserIndex]; $selectedSearchResult = $session->userSearchResults[$selectedUserIndex];
...@@ -43,7 +43,7 @@ Flight::route('POST /join', function() { ...@@ -43,7 +43,7 @@ Flight::route('POST /join', function() {
$token = RAP\Util::createNewToken(); $token = RAP\Util::createNewToken();
$dao->createJoinRequest($token, $session->user->id, $targetUserId); $dao->createJoinRequest($token, $session->user->id, $targetUserId);
RAP\MailSender::sendJoinEmail($selectedSearchResult->getUser(), $session->user); $mailSender->sendJoinEmail($selectedSearchResult->getUser(), $session->user, $token);
echo $selectedSearchResult->userDisplayText; echo $selectedSearchResult->userDisplayText;
}); });
......
...@@ -55,6 +55,7 @@ switch ($DATABASE['dbtype']) { ...@@ -55,6 +55,7 @@ switch ($DATABASE['dbtype']) {
$callbackHandler = new RAP\CallbackHandler($dao, $BASE_PATH, $CALLBACKS); $callbackHandler = new RAP\CallbackHandler($dao, $BASE_PATH, $CALLBACKS);
$userHandler = new RAP\UserHandler($dao, $GROUPER); $userHandler = new RAP\UserHandler($dao, $GROUPER);
$mailSender = new RAP\MailSender($_SERVER['HTTP_HOST'], $BASE_PATH);
function startSession() { function startSession() {
session_start(); session_start();
......
...@@ -47,5 +47,41 @@ Flight::route('GET ' . $WS_PREFIX . '/user', function() { ...@@ -47,5 +47,41 @@ Flight::route('GET ' . $WS_PREFIX . '/user', function() {
echo json_encode($users); echo json_encode($users);
}); });
/**
* Create new user from identity data. Return the new user.
*/
Flight::route('POST ' . $WS_PREFIX . '/user', function() {
global $userHandler;
$postData = Flight::request()->data;
$user = new RAP\User();
$identity = new RAP\Identity($postData['type']);
$identity->email = $postData['email'];
$identity->typedId = $postData['typedId'];
if (isset($postData['name'])) {
$identity->name = $postData['name'];
}
if (isset($postData['surname'])) {
$identity->surname = $postData['surname'];
}
if (isset($postData['institution'])) {
$identity->institution = $postData['institution'];
}
if (isset($postData['eppn'])) {
$identity->eppn = $postData['eppn'];
}
$user->addIdentity($identity);
$userHandler->saveUser($user);
echo json_encode($user);
});
Flight::route('GET ' . $WS_PREFIX . '/test', function() { Flight::route('GET ' . $WS_PREFIX . '/test', function() {
}); });
<?php foreach ($user->identities as $identity) { ?> <?php foreach ($user->identities as $identity) { ?>
<dl class="dl-horizontal"> <dl class="dl-horizontal">
<dt> <dt>
<?php if (!isset($readonly)) { ?>
<?php if ($identity->primary) { ?> <?php if ($identity->primary) { ?>
<span class="primary-identity-icon" data-toggle="tooltip" data-placement="left" title="This is your primary identity. You will receive email messages on the address related to this identity."> <span class="primary-identity-icon" data-toggle="tooltip" data-placement="left" title="This is your primary identity. You will receive email messages on the address related to this identity.">
<span class="glyphicon glyphicon-star"></span> <span class="glyphicon glyphicon-star"></span>
...@@ -12,13 +13,14 @@ ...@@ -12,13 +13,14 @@
</a> </a>
</span> </span>
<?php } ?> <?php } ?>
<?php } ?>
Type Type
</dt> </dt>
<dd><?php echo $identity->type; ?></dd> <dd><?php echo $identity->type; ?></dd>
<dt>E-mail</dt> <dt>E-mail</dt>
<dd><?php echo $identity->email; ?></dd> <dd><?php echo $identity->email; ?></dd>
<?php if ($identity->eppn !== null) { ?> <?php if ($identity->eppn !== null) { ?>
<dt>EduPersonPrincipalName</dt> <dt><abbr title="EduPerson Principal Name, an unique identifier used into federations.">EPPN</abbr></dt>
<dd><?php echo $identity->eppn; ?></dd> <dd><?php echo $identity->eppn; ?></dd>
<?php } ?> <?php } ?>
<?php if ($identity->name !== null) { ?> <?php if ($identity->name !== null) { ?>
......
...@@ -63,6 +63,9 @@ ...@@ -63,6 +63,9 @@
// Add click event handler to join request button // Add click event handler to join request button
$(document).on('click', '#send-join-request-btn', sendJoinRequest); $(document).on('click', '#send-join-request-btn', sendJoinRequest);
// Add event handler for closing the info alert message.
// This is used instead of data-dismiss="alert" in order to maintain
// the alert inside the DOM and be able to show it again if necessary.
$(document).on('click', '#info-message-alert .close', function () { $(document).on('click', '#info-message-alert .close', function () {
$('#info-message-alert').addClass('hide'); $('#info-message-alert').addClass('hide');
}); });
......
...@@ -12,6 +12,7 @@ include 'include/header.php'; ...@@ -12,6 +12,7 @@ include 'include/header.php';
<div class="panel-body"> <div class="panel-body">
<?php <?php
$user = $applicantUser; $user = $applicantUser;
$readOnly = true;
include 'include/user-data.php'; include 'include/user-data.php';
?> ?>
</div> </div>
...@@ -25,6 +26,7 @@ include 'include/header.php'; ...@@ -25,6 +26,7 @@ include 'include/header.php';
<div class="panel-body"> <div class="panel-body">
<?php <?php
$user = $targetUser; $user = $targetUser;
$readOnly = true;
include 'include/user-data.php'; include 'include/user-data.php';
?> ?>
</div> </div>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment