From 4e0c3d3a8787c4751e50167519444fb70ca68534 Mon Sep 17 00:00:00 2001
From: Sonia Zorba <zorba@oats.inaf.it>
Date: Mon, 21 May 2018 15:59:21 +0200
Subject: [PATCH] Changes for being compliant with new GDPR law

---
 auth/oauth2/facebook_token.php |  5 +-
 auth/oauth2/google_token.php   |  5 +-
 auth/oauth2/linkedin_token.php |  5 +-
 auth/saml2/aai.php             |  5 +-
 auth/x509/certlogin.php        | 90 ++++++++++++----------------------
 classes/SessionData.php        |  4 ++
 classes/X509Data.php           | 19 +++++++
 include/front-controller.php   | 50 +++++++++++++++++--
 js/tou.js                      |  7 +++
 sql/setup-database.sql         |  1 +
 views/tou-check.php            | 44 +++++++++++++++++
 11 files changed, 169 insertions(+), 66 deletions(-)
 create mode 100644 js/tou.js
 create mode 100644 views/tou-check.php

diff --git a/auth/oauth2/facebook_token.php b/auth/oauth2/facebook_token.php
index d438314..52f66a0 100755
--- a/auth/oauth2/facebook_token.php
+++ b/auth/oauth2/facebook_token.php
@@ -98,7 +98,10 @@ if ($user === null) {
 
     $user->addIdentity($identity);
 
-    $userHandler->saveUser($user);
+    $session->userToLogin = $user;
+    $session->save();
+    header('Location: ' . $BASE_PATH . '/tou-check');
+    die();
 }
 
 $auditLog->info("LOGIN,Facebook," . $user->id);
diff --git a/auth/oauth2/google_token.php b/auth/oauth2/google_token.php
index c5a5bd4..16831cc 100644
--- a/auth/oauth2/google_token.php
+++ b/auth/oauth2/google_token.php
@@ -92,7 +92,10 @@ if ($client->getAccessToken()) {
 
         $user->addIdentity($identity);
 
-        $userHandler->saveUser($user);
+        $session->userToLogin = $user;
+        $session->save();
+        header('Location: ' . $BASE_PATH . '/tou-check');
+        die();
     }
 
     $auditLog->info("LOGIN,Google," . $user->id);
diff --git a/auth/oauth2/linkedin_token.php b/auth/oauth2/linkedin_token.php
index fde3cb8..64a5647 100644
--- a/auth/oauth2/linkedin_token.php
+++ b/auth/oauth2/linkedin_token.php
@@ -118,7 +118,10 @@ if ($info2['http_code'] === 200) {
 
         $user->addIdentity($identity);
 
-        $userHandler->saveUser($user);
+        $session->userToLogin = $user;
+        $session->save();
+        header('Location: ' . $BASE_PATH . '/tou-check');
+        die();
     }
 
     $auditLog->info("LOGIN,LinkedIn," . $user->id);
diff --git a/auth/saml2/aai.php b/auth/saml2/aai.php
index cd89610..0b82779 100644
--- a/auth/saml2/aai.php
+++ b/auth/saml2/aai.php
@@ -57,7 +57,10 @@ if (isset($_SERVER['Shib-Session-ID'])) {
 
         $user->addIdentity($identity);
 
-        $userHandler->saveUser($user);
+        $session->userToLogin = $user;
+        $session->save();
+        header('Location: ' . $BASE_PATH . '/tou-check');
+        die();
     }
 
     $auditLog->info("LOGIN,eduGAIN," . $user->id);
diff --git a/auth/x509/certlogin.php b/auth/x509/certlogin.php
index 61085fe..c811cd8 100644
--- a/auth/x509/certlogin.php
+++ b/auth/x509/certlogin.php
@@ -32,66 +32,38 @@
 include '../../include/init.php';
 startSession();
 
-function saveUserFromX509Data($x509Data) {
-
-    global $session, $userHandler;
-
-    $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);
-
-    $userHandler->saveUser($user);
-
-    $session->x509DataToRegister = null;
-    $session->save();
-
-    return $user;
-}
-
-/**
- * We want to extract name and surname from the X.509 certificate, however X.509
- * puts name and surname together (inside the CN field).
- * If name and surname are single words it is possible to retrieve them splitting
- * on the space character, otherwise the user has to choose the correct combination.
- * In that case partial X.509 data is temporarily stored into the user session and
- * the page views/x509-name-surname.php is shown to the user before completing the
- * registration, in order to allow him/her selecting the correct name and surname.
- */
-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 = $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);
-            }
+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 = $userHandler->findUserByIdentity(RAP\Identity::X509, $x509Data->serialNumber);
+
+    if ($user === null) {
+        /**
+         * We want to extract name and surname from the X.509 certificate, however X.509
+         * puts name and surname together (inside the CN field).
+         * If name and surname are single words it is possible to retrieve them splitting
+         * on the space character, otherwise the user has to choose the correct combination.
+         * In that case partial X.509 data is temporarily stored into the user session and
+         * the page views/x509-name-surname.php is shown to the user before completing the
+         * registration, in order to allow him/her selecting the correct name and surname.
+         */
+        if ($x509Data->name === null) {
+            $session->x509DataToRegister = $x509Data;
+            $session->save();
+            header('Location: ' . $BASE_PATH . '/x509-name-surname');
+        } else {
+            $session->userToLogin = $x509Data->toUser();
+            $session->save();
+            header('Location: ' . $BASE_PATH . '/tou-check');
         }
+        die();
     } else {
-        http_response_code(500);
-        die("Unable to verify client certificate");
+        $auditLog->info("LOGIN,X.509," . $user->id);
+        $callbackHandler->manageLoginRedirect($user, $session);
     }
+} else {
+    http_response_code(500);
+    die("Unable to verify client certificate");
 }
-
-$auditLog->info("LOGIN,X.509," . $user->id);
-$callbackHandler->manageLoginRedirect($user, $session);
diff --git a/classes/SessionData.php b/classes/SessionData.php
index 294e934..ef5c8a8 100644
--- a/classes/SessionData.php
+++ b/classes/SessionData.php
@@ -37,6 +37,10 @@ class SessionData {
     public $user;
     public $userSearchResults;
     public $x509DataToRegister;
+    // user which is going to perform the login (we need to store this in the
+    // session because we need to check the Terms of Use user consensus, so we
+    // redirect to another page after retrieving user data.
+    public $userToLogin;
 
     /**
      * @todo: move DAO away from here
diff --git a/classes/X509Data.php b/classes/X509Data.php
index bede4cd..ddfb402 100644
--- a/classes/X509Data.php
+++ b/classes/X509Data.php
@@ -88,6 +88,9 @@ class X509Data {
                 $this->email = $AyAlt[1];
             }
         }
+        if ($this->email === null && isset($parsedX509["subject"]) && isset($parsedX509["subject"]["emailAddress"])) {
+            $this->email = $parsedX509["subject"]["emailAddress"];
+        }
 
         $this->serialNumber = $parsedX509["serialNumber"];
 
@@ -200,4 +203,20 @@ class X509Data {
         return $parsedData;
     }
 
+    public function toUser() {
+
+        $user = new User();
+
+        $identity = new Identity(Identity::X509);
+        $identity->email = $this->email;
+        $identity->name = $this->name;
+        $identity->surname = $this->surname;
+        $identity->typedId = $this->serialNumber;
+        $identity->institution = $this->institution;
+
+        $user->addIdentity($identity);
+
+        return $user;
+    }
+
 }
diff --git a/include/front-controller.php b/include/front-controller.php
index 2d1c405..1fbabb7 100644
--- a/include/front-controller.php
+++ b/include/front-controller.php
@@ -159,6 +159,7 @@ Flight::route('GET /x509-name-surname', function() {
     } else {
         // Redirect to index
         header("Location: " . $BASE_PATH);
+        die();
     }
 });
 
@@ -169,12 +170,55 @@ Flight::route('GET /x509-name-surname', function() {
 Flight::route('POST /submit-x509-name', function() {
 
     $selectedNameIndex = Flight::request()->data['selected-name'];
-
+    
+    error_log('index=' . $selectedNameIndex);
+    
     startSession();
     global $session, $BASE_PATH;
-
+    
     if ($session->x509DataToRegister !== null) {
         $session->x509DataToRegister->selectCandidateName($selectedNameIndex);
-        header("Location: " . $BASE_PATH . '/x509');
+        $session->userToLogin = $session->x509DataToRegister->toUser();
+        $session->x509DataToRegister = null;
+        $session->save();
+        header("Location: " . $BASE_PATH . '/tou-check');
+        die();
+    } else {
+        die('X.509 data not returned');
+    }
+});
+
+Flight::route('GET /tou-check', function() {
+
+    startSession();
+    global $session, $BASE_PATH, $VERSION;
+
+    if ($session->userToLogin === null) {
+        die("User data not retrieved.");
+    } else {
+        Flight::render('tou-check.php', array('title' => 'Terms of Use acceptance',
+            'user' => $session->userToLogin,
+            'version' => $VERSION,
+            'registration_url' => $BASE_PATH . '/register'));
+    }
+});
+
+Flight::route('GET /register', function() {
+
+    startSession();
+    global $session, $userHandler, $auditLog, $callbackHandler;
+
+    if ($session->userToLogin === null) {
+        die("User data not retrieved.");
+    } else {
+
+        $user = $session->userToLogin;
+        $userHandler->saveUser($user);
+
+        $session->userToLogin = null;
+        $session->save();
+
+        $auditLog->info("LOGIN," . $user->identities[0]->type . "," . $user->id);
+        $callbackHandler->manageLoginRedirect($user, $session);
     }
 });
diff --git a/js/tou.js b/js/tou.js
new file mode 100644
index 0000000..a3f42bd
--- /dev/null
+++ b/js/tou.js
@@ -0,0 +1,7 @@
+$('#tou-ck').on('change', function () {
+    if ($(this).is(':checked')) {
+        $('#tou-submit').removeClass('hide');
+    } else {
+        $('#tou-submit').addClass('hide');
+    }
+});
diff --git a/sql/setup-database.sql b/sql/setup-database.sql
index 8bb38e0..d5b4328 100644
--- a/sql/setup-database.sql
+++ b/sql/setup-database.sql
@@ -14,6 +14,7 @@ CREATE TABLE `identity` (
   `surname` varchar(255) DEFAULT NULL,
   `institution` varchar(255) DEFAULT NULL,
   `eppn` varchar(255) DEFAULT NULL,
+  `tou_accepted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
   PRIMARY KEY (`id`),
   FOREIGN KEY (`user_id`) REFERENCES `user`(`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/views/tou-check.php b/views/tou-check.php
new file mode 100644
index 0000000..a72f88a
--- /dev/null
+++ b/views/tou-check.php
@@ -0,0 +1,44 @@
+<?php
+include 'include/header.php';
+?>
+
+<br/>
+<div class="text-center">
+    <p>If you proceed, following data will be stored into IA2 user database:</p>
+</div>
+
+<div class="row">
+    <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
+        <div class="panel">
+            <div class="panel-body">
+                <?php
+                $readOnly = true;
+                include 'include/user-data.php';
+                ?>        
+            </div>
+        </div>
+    </div>
+</div>
+
+<div class="row text-center">
+    <strong>
+        <span class="glyphicon glyphicon-info-sign"></span>
+        For using IA2 services you need to accept our <a href="https://sso.ia2.inaf.it/home/privacy.php?lang=en" target="blank_">privacy policy</a>.
+    </strong>
+    <div class="checkbox">
+        <label>
+            <input type="checkbox" id="tou-ck" />
+            I accept IA2 services Terms of Use.
+        </label>
+    </div>
+    <form method="GET" action="<?php echo $registration_url; ?>">
+        <input type="submit" class="btn btn-primary hide" id="tou-submit" value="Submit" />
+    </form>
+</div>
+
+<script src="js/tou.js"></script>
+
+<br/>
+
+<?php
+include 'include/footer.php';
-- 
GitLab