diff --git a/classes/login/FacebookLogin.php b/classes/login/FacebookLogin.php index 3d43507857d45e407a912cf109277d6dd0df5a55..b985d529e1d52ce0f8a3fb22e5967e1504b80d62 100644 --- a/classes/login/FacebookLogin.php +++ b/classes/login/FacebookLogin.php @@ -5,7 +5,7 @@ namespace RAP; class FacebookLogin extends LoginHandler { public function __construct(Locator $locator) { - parent::__construct($locator, Identity::FACEBOOK); + parent::__construct($locator); } public function login(): string { @@ -65,13 +65,13 @@ class FacebookLogin extends LoginHandler { $fbUser = $response->getGraphUser(); - $typedId = $fbUser["id"]; + $identity = new Identity(Identity::FACEBOOK); + $identity->typedId = $fbUser["id"]; + $identity->email = $fbUser["email"]; + $identity->name = $fbUser["first_name"]; + $identity->surname = $fbUser["last_name"]; - return $this->onIdentityDataReceived($typedId, function($identity) use($fbUser) { - $identity->email = $fbUser["email"]; - $identity->name = $fbUser["first_name"]; - $identity->surname = $fbUser["last_name"]; - }); + return $this->onIdentityDataReceived($identity); } } diff --git a/classes/login/GoogleLogin.php b/classes/login/GoogleLogin.php index 82079aae58bb820a21216e121b8cff8007ed5a89..b0c1143ad751c9e150087942572095fa151ae384 100644 --- a/classes/login/GoogleLogin.php +++ b/classes/login/GoogleLogin.php @@ -5,7 +5,7 @@ namespace RAP; class GoogleLogin extends LoginHandler { public function __construct(Locator $locator) { - parent::__construct($locator, Identity::GOOGLE); + parent::__construct($locator); } public function login() { @@ -56,11 +56,12 @@ class GoogleLogin extends LoginHandler { $typedId = explode('/', $res->getResourceName())[1]; - return $this->onIdentityDataReceived($typedId, function($identity) use($emailAddresses, $name, $surname) { - $identity->email = $emailAddresses[0]; - $identity->name = $name; - $identity->surname = $surname; - }); + $identity = new Identity(Identity::GOOGLE); + $identity->typedId = $typedId; + $identity->email = $emailAddresses[0]; + $identity->name = $name; + $identity->surname = $surname; + return $this->onIdentityDataReceived($identity); } else { // Redirect to Google authorization URL for obtaining an access token $authUrl = $client->createAuthUrl(); diff --git a/classes/login/LinkedInLogin.php b/classes/login/LinkedInLogin.php index 57c4f3b33ec6d73907b92fc588b27595c7ca2330..5a646bedf5d85af00dbcbce2d4fc42ac2d2d66a0 100644 --- a/classes/login/LinkedInLogin.php +++ b/classes/login/LinkedInLogin.php @@ -5,7 +5,7 @@ namespace RAP; class LinkedInLogin extends LoginHandler { public function __construct(Locator $locator) { - parent::__construct($locator, Identity::LINKEDIN); + parent::__construct($locator); } public function login(): string { @@ -128,11 +128,13 @@ class LinkedInLogin extends LoginHandler { die($errorMessage); } - return $this->onIdentityDataReceived($typedId, function($identity) use($data, $data2) { - $identity->email = $data2['elements'][0]['handle~']['emailAddress']; - $identity->name = $data['localizedFirstName']; - $identity->surname = $data['localizedLastName']; - }); + $identity = new Identity(Identity::LINKEDIN); + $identity->typedId = $typedId; + $identity->email = $data2['elements'][0]['handle~']['emailAddress']; + $identity->name = $data['localizedFirstName']; + $identity->surname = $data['localizedLastName']; + + return $this->onIdentityDataReceived($identity); } else { //show information regarding the error $errorMessage = "Error: LinkedIn server response code: " . $info2['http_code'] . " - "; diff --git a/classes/login/LoginHandler.php b/classes/login/LoginHandler.php index 5232ae0100c4a7eb7a4e92192aae6af5aacfaeb8..79148b82f8a5532150df2a6c67a89e104a57bd29 100644 --- a/classes/login/LoginHandler.php +++ b/classes/login/LoginHandler.php @@ -5,22 +5,26 @@ namespace RAP; class LoginHandler { protected $locator; - private $identityType; - public function __construct(Locator $locator, string $identityType) { + public function __construct(Locator $locator) { $this->locator = $locator; - $this->identityType = $identityType; - $this->locator->getSession()->setLoginIdentityType($identityType); } - public function onIdentityDataReceived(string $typedId, \Closure $fillIdentityData): string { - - $user = $this->locator->getUserDAO()->findUserByIdentity($this->identityType, $typedId); - + /** + * Returns redirect URL. + */ + public function onIdentityDataReceived(Identity $identity): string { + + $this->locator->getSession()->setLoginIdentityType($identity->type); + + $userDao = $this->locator->getUserDAO(); + + $user = $userDao->findUserByIdentity($identity->type, $identity->typedId); + if ($user === null) { - return $this->handleNewIdentity($typedId, $fillIdentityData); + return $this->handleNewIdentity($identity); } else { - $this->updateUser($user, $typedId, $fillIdentityData); + $this->updateUser($user, $identity); } $session = $this->locator->getSession(); @@ -32,15 +36,15 @@ class LoginHandler { return $this->getAfterLoginRedirect($user); } - protected function handleNewIdentity(string $typedId, \Closure $fillIdentityData): string { + protected function handleNewIdentity(Identity $identity): string { $session = $this->locator->getSession(); if ($session->getUser() !== null && $session->getAction() === 'join') { - $userToJoin = $this->getNewUser($typedId, $fillIdentityData); + $userToJoin = $this->getNewUser($identity); return $this->showConfirmJoin($userToJoin); } else { - return $this->redirectToTOUCheck($typedId, $fillIdentityData); + return $this->redirectToTOUCheck($identity); } } @@ -52,21 +56,18 @@ class LoginHandler { /** * Stores the data into session and Redirect to Term of Use acceptance page. */ - private function redirectToTOUCheck(string $typedId, \Closure $fillIdentityData): string { + private function redirectToTOUCheck(Identity $identity): string { // Create new user - $user = $this->getNewUser($typedId, $fillIdentityData); + $user = $this->getNewUser($identity); $this->locator->getSession()->setUser($user); return $this->locator->getBasePath() . '/tou-check'; } - private function getNewUser(string $typedId, \Closure $fillIdentityData): User { + private function getNewUser(Identity $identity): User { $user = new User(); - $identity = new Identity($this->identityType); - $identity->typedId = $typedId; - $fillIdentityData($identity); $user->addIdentity($identity); return $user; } @@ -74,16 +75,25 @@ class LoginHandler { /** * Update user with fresh information received by IdP. Useful for keeping email address always updated. */ - private function updateUser(User $user, string $typedId, \Closure $fillIdentityData): void { - $identity = $user->getIdentityByTypedId($typedId); - $fillIdentityData($identity); - $this->locator->getUserDAO()->updateIdentity($identity); + private function updateUser(User $user, Identity $identity): void { + $savedIdentity = $user->getIdentityByTypedId($identity->typedId); + $savedIdentity->email = $identity->email; + if($identity->name !== null) { + $savedIdentity->name = $identity->name; + } + if($identity->surname !== null) { + $savedIdentity->surname = $identity->surname; + } + if($identity->institution !== null) { + $savedIdentity->institution = $identity->institution; + } + $this->locator->getUserDAO()->updateIdentity($savedIdentity); } public function getAfterLoginRedirect(User $user): string { $session = $this->locator->getSession(); - $this->locator->getAuditLogger()->info("LOGIN," . $this->identityType . "," . $user->id); + $this->locator->getAuditLogger()->info("LOGIN," . $session->getLoginIdentityType() . "," . $user->id); if ($session->getOAuth2RequestData() !== null) { $session->setUser($user); diff --git a/classes/login/OrcidLogin.php b/classes/login/OrcidLogin.php index 8568a73e48cbb26494ab732852228270b7860e52..e49ccf19c679dbc7baf45eddf2c53a4d180da4bc 100644 --- a/classes/login/OrcidLogin.php +++ b/classes/login/OrcidLogin.php @@ -5,7 +5,7 @@ namespace RAP; class OrcidLogin extends LoginHandler { public function __construct(Locator $locator) { - parent::__construct($locator, Identity::ORCID); + parent::__construct($locator); } public function login(): string { @@ -39,15 +39,17 @@ class OrcidLogin extends LoginHandler { throw new \Exception("ORCID didn't return the email"); } - return $this->onIdentityDataReceived($orcid_id, function($identity) use($orcid_data) { - $identity->email = $email = $orcid_data['person']['emails']['email'][0]['email']; - $identity->name = $orcid_data['person']['name']['given-names']['value']; - $identity->surname = $orcid_data['person']['name']['family-name']['value']; - $employmentSummary = $orcid_data['activities-summary']['employments']['employment-summary']; - if (count($employmentSummary) > 0) { - $identity->institution = $employmentSummary[0]['organization']['name']; - } - }); + $identity = new Identity(Identity::ORCID); + $identity->typedId = $orcid_id; + $identity->email = $email = $orcid_data['person']['emails']['email'][0]['email']; + $identity->name = $orcid_data['person']['name']['given-names']['value']; + $identity->surname = $orcid_data['person']['name']['family-name']['value']; + $employmentSummary = $orcid_data['activities-summary']['employments']['employment-summary']; + if (count($employmentSummary) > 0) { + $identity->institution = $employmentSummary[0]['organization']['name']; + } + + return $this->onIdentityDataReceived($identity); } private function getAccessTokenFromCode($code): array { diff --git a/classes/login/ShibbolethLogin.php b/classes/login/ShibbolethLogin.php index bea9d4de0a09aafb66f3c974d2f975e679e970b1..77dc696fc856d18b42d848f9ffd97ad43404f718 100644 --- a/classes/login/ShibbolethLogin.php +++ b/classes/login/ShibbolethLogin.php @@ -5,7 +5,7 @@ namespace RAP; class ShibbolethLogin extends LoginHandler { public function __construct(Locator $locator) { - parent::__construct($locator, Identity::EDU_GAIN); + parent::__construct($locator); } public function login() { @@ -19,17 +19,17 @@ class ShibbolethLogin extends LoginHandler { // The persistent id should be a more appropriate identifier, however at IA2 // we need to import all INAF user into RAP, even if they will never register, // and in that case we know only their eppn. - - return $this->onIdentityDataReceived($eppn, function($identity) use($eppn) { - $identity->email = $_SERVER['mail']; - if (isset($_SERVER['givenName']) && $_SERVER['givenName'] !== 'N/A') { - $identity->name = $_SERVER['givenName']; - } - if (isset($_SERVER['sn']) && $_SERVER['sn'] !== 'N/A') { - $identity->surname = $_SERVER['sn']; - } - $identity->eppn = $eppn; - }); + $identity = new Identity(Identity::EDU_GAIN); + $identity->typedId = $eppn; + $identity->email = $_SERVER['mail']; + if (isset($_SERVER['givenName']) && $_SERVER['givenName'] !== 'N/A') { + $identity->name = $_SERVER['givenName']; + } + if (isset($_SERVER['sn']) && $_SERVER['sn'] !== 'N/A') { + $identity->surname = $_SERVER['sn']; + } + $identity->eppn = $eppn; + return $this->onIdentityDataReceived($identity); } else { throw new ServerErrorException("Shib-Session-ID not found!"); } diff --git a/classes/login/X509Login.php b/classes/login/X509Login.php index b050bbacf4e653c625091223fa393901cae5fb41..70f6e24dba467b90ba48f73f936c2120206ca508 100644 --- a/classes/login/X509Login.php +++ b/classes/login/X509Login.php @@ -7,7 +7,7 @@ class X509Login extends LoginHandler { private $x509Data; public function __construct(Locator $locator) { - parent::__construct($locator, Identity::X509); + parent::__construct($locator); } public function login(): string { @@ -17,9 +17,7 @@ class X509Login extends LoginHandler { $x509Data = X509Data::parse($_SERVER); $this->x509Data = $x509Data; - return $this->onIdentityDataReceived($x509Data->serialNumber, function($identity) use ($x509Data) { - $this->fillIdentity($identity, $x509Data); - }); + return $this->onIdentityDataReceived($this->getIdentity($x509Data)); } else { http_response_code(500); die("Unable to verify client certificate"); @@ -29,9 +27,7 @@ class X509Login extends LoginHandler { } public function afterNameSurnameSelection($x509Data) { - $redirect = $this->onIdentityDataReceived($x509Data->serialNumber, function($identity) use ($x509Data) { - $this->fillIdentity($identity, $x509Data); - }); + $redirect = $this->onIdentityDataReceived($this->getIdentity($x509Data)); $session = $this->locator->getSession(); $session->setX509DataToRegister(null); @@ -39,11 +35,14 @@ class X509Login extends LoginHandler { return $redirect; } - private function fillIdentity($identity, $x509Data) { + private function getIdentity($x509Data): Identity { + $identity = new Identity(Identity::X509); + $identity->typedId = $x509Data->serialNumber; $identity->email = $x509Data->email; $identity->name = $x509Data->name; $identity->surname = $x509Data->surname; $identity->institution = $x509Data->institution; + return $identity; } /** @@ -55,7 +54,7 @@ class X509Login extends LoginHandler { * 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. */ - protected function handleNewIdentity(string $typedId, \Closure $fillIdentityData): string { + protected function handleNewIdentity(Identity $identity): string { $session = $this->locator->getSession(); @@ -63,7 +62,7 @@ class X509Login extends LoginHandler { $session->setX509DataToRegister($this->x509Data); return $this->locator->getBasePath() . '/x509-name-surname'; } else { - return parent::handleNewIdentity($typedId, $fillIdentityData); + return parent::handleNewIdentity($identity); } } diff --git a/classes/model/SessionData.php b/classes/model/SessionData.php index ba0e3ba51bc02eab63fe1530dc5492429226a5fc..e1916dc9d737457e4b158450a0e3299c5b3112e6 100644 --- a/classes/model/SessionData.php +++ b/classes/model/SessionData.php @@ -67,6 +67,9 @@ class SessionData { return $this->autojoin; } + /** + * Used for logging the identity type chosen for the login at the end of the login process + */ public function setLoginIdentityType(string $loginIdentityType): void { $this->loginIdentityType = $loginIdentityType; $this->save(); diff --git a/include/front-controller.php b/include/front-controller.php index 9685ca41e33a02628562cefdafa6dbab5e7bfe27..3ef1c86680d9da4991ce8d734cd4007d80c92bb0 100644 --- a/include/front-controller.php +++ b/include/front-controller.php @@ -314,7 +314,7 @@ Flight::route('POST /confirm-join', function() { if ($user === null) { die("Unable to find user to join"); } else { - $loginHandler = new \RAP\LoginHandler($locator, $locator->getSession()->getLoginIdentityType()); + $loginHandler = new \RAP\LoginHandler($locator); Flight::redirect($loginHandler->getAfterLoginRedirect($user)); } }); @@ -334,7 +334,7 @@ Flight::route('GET /register', function() { } else { $locator->getUserHandler()->saveUser($user); - $loginHandler = new \RAP\LoginHandler($locator, $locator->getSession()->getLoginIdentityType()); + $loginHandler = new \RAP\LoginHandler($locator); Flight::redirect($loginHandler->getAfterLoginRedirect($user)); } }); diff --git a/tests/LoginHandlerTest.php b/tests/LoginHandlerTest.php index c164267ee7e9de422d4e0ce9550c71016bb930fe..e8cf6f12fe2fd6be1339e5bec2214981cbf5e4e6 100644 --- a/tests/LoginHandlerTest.php +++ b/tests/LoginHandlerTest.php @@ -33,9 +33,7 @@ final class LoginHandlerTest extends TestCase { } public function testTOUCheck(): void { - $redirect = $this->loginHandler->onIdentityDataReceived('123', function($identity) { - $identity->email = 'test@example.com'; - }); + $redirect = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1()); $this->assertEquals('http://rap-ia2/tou-check', $redirect); } @@ -54,9 +52,7 @@ final class LoginHandlerTest extends TestCase { $this->userDaoStub->expects($this->once()) ->method('updateIdentity')->with($this->anything()); - $redirect = $this->loginHandler->onIdentityDataReceived('123', function($identity) { - $identity->email = 'test2@example.com'; - }); + $redirect = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1NewEmail()); // verify update $this->assertEquals('test2@example.com', $user->identities[0]->email); @@ -71,9 +67,7 @@ final class LoginHandlerTest extends TestCase { $this->sessionStub->method('getUser')->willReturn($user); $this->sessionStub->method('getAction')->willReturn('join'); - $redirect = $this->loginHandler->onIdentityDataReceived('456', function($identity) { - $identity->email = 'test3@example.com'; - }); + $redirect = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity2()); $this->assertEquals('http://rap-ia2/confirm-join', $redirect); } @@ -92,9 +86,7 @@ final class LoginHandlerTest extends TestCase { $this->userDaoStub->method('findUserByIdentity')->willReturn($user2); - $redirect = $this->loginHandler->onIdentityDataReceived('456', function($identity) { - $identity->email = 'test3@example.com'; - }); + $redirect = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity2()); $this->assertEquals('http://rap-ia2/confirm-join', $redirect); } @@ -135,9 +127,7 @@ final class LoginHandlerTest extends TestCase { $this->userDaoStub->method('findUserByIdentity')->willReturn($user); - $redirect = $this->loginHandler->onIdentityDataReceived('123', function($identity) { - $identity->email = 'test@example.com'; - }); + $redirect = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1()); $this->assertEquals('http://rap-ia2/account', $redirect); } @@ -154,4 +144,28 @@ final class LoginHandlerTest extends TestCase { return $user; } + private function getFakeIdentity1(): \RAP\Identity { + + $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN); + $identity->typedId = '123'; + $identity->email = 'test@example.com'; + return $identity; + } + + private function getFakeIdentity1NewEmail(): \RAP\Identity { + + $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN); + $identity->typedId = '123'; + $identity->email = 'test2@example.com'; + return $identity; + } + + private function getFakeIdentity2(): \RAP\Identity { + + $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN); + $identity->typedId = '456'; + $identity->email = 'test3@example.com'; + return $identity; + } + }