From 1d23bd3433fe9ee99ba4cb5cdffce42b7c82f01f Mon Sep 17 00:00:00 2001 From: ChrisWayFor Date: Thu, 12 Dec 2024 16:29:31 +0100 Subject: [PATCH] Fix linkedin auth considering new apis --- .../ResourceOwner/LinkedinResourceOwner.php | 30 +++-------- src/OAuth/Response/LinkedinUserResponse.php | 52 ++----------------- 2 files changed, 10 insertions(+), 72 deletions(-) diff --git a/src/OAuth/ResourceOwner/LinkedinResourceOwner.php b/src/OAuth/ResourceOwner/LinkedinResourceOwner.php index 0e1318c19..66f0e7603 100644 --- a/src/OAuth/ResourceOwner/LinkedinResourceOwner.php +++ b/src/OAuth/ResourceOwner/LinkedinResourceOwner.php @@ -26,12 +26,12 @@ final class LinkedinResourceOwner extends GenericOAuth2ResourceOwner * {@inheritdoc} */ protected array $paths = [ - 'identifier' => 'id', - 'nickname' => 'emailAddress', - 'firstname' => 'firstName', - 'lastname' => 'lastName', - 'email' => 'emailAddress', - 'profilepicture' => 'profilePicture', + 'identifier' => 'sub', + 'nickname' => 'email', + 'firstname' => 'given_name', + 'lastname' => 'family_name', + 'email' => 'email', + 'profilepicture' => 'picture', ]; /** @@ -41,22 +41,6 @@ public function getUserInformation(array $accessToken, array $extraParameters = { $response = parent::getUserInformation($accessToken, $extraParameters); - $responseData = $response->getData(); - // The user info returned by /me doesn't contain the email so we make an extra request to fetch it - $content = $this->httpRequest( - $this->normalizeUrl($this->options['email_url'], $extraParameters), - null, - ['Authorization' => 'Bearer '.$accessToken['access_token']] - ); - - $emailResponse = $this->getResponseContent($content); - if (isset($emailResponse['elements']) && \count($emailResponse['elements']) > 0) { - $responseData['emailAddress'] = $emailResponse['elements'][0]['handle~']['emailAddress']; - } - // errors not handled because I don't see any relevant thing to do with them - - $response->setData($responseData); - return $response; } @@ -100,7 +84,7 @@ protected function configureOptions(OptionsResolver $resolver) 'scope' => 'r_liteprofile r_emailaddress', 'authorization_url' => 'https://www.linkedin.com/oauth/v2/authorization', 'access_token_url' => 'https://www.linkedin.com/oauth/v2/accessToken', - 'infos_url' => 'https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))', + 'infos_url' => 'https://api.linkedin.com/v2/userinfo', 'email_url' => 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', 'user_response_class' => LinkedinUserResponse::class, diff --git a/src/OAuth/Response/LinkedinUserResponse.php b/src/OAuth/Response/LinkedinUserResponse.php index 6636e0783..3b87021b3 100644 --- a/src/OAuth/Response/LinkedinUserResponse.php +++ b/src/OAuth/Response/LinkedinUserResponse.php @@ -18,7 +18,7 @@ final class LinkedinUserResponse extends PathUserResponse */ public function getFirstName(): ?string { - return $this->getPreferredLocaleValue('firstname'); + return $this->getValueForPath('firstname'); } /** @@ -26,7 +26,7 @@ public function getFirstName(): ?string */ public function getLastName(): ?string { - return $this->getPreferredLocaleValue('lastname'); + return $this->getValueForPath('lastname'); } /** @@ -34,53 +34,7 @@ public function getLastName(): ?string */ public function getProfilePicture(): ?string { - // https://docs.microsoft.com/en-us/linkedin/shared/references/v2/profile/profile-picture - /** @var array>>> $profilePicture */ - $profilePicture = $this->getValueForPath('profilepicture'); - if ( - !\is_array($profilePicture) - || !isset($profilePicture['displayImage~']['elements']) - || 0 === \count($profilePicture['displayImage~']['elements']) - ) { - return null; - } - - $publicElements = array_filter($profilePicture['displayImage~']['elements'], static function ($element) { - return 'PUBLIC' === $element['authorizationMethod']; - }); - if (0 === \count($publicElements)) { - return null; - } - - // the last images seems to always be the one with the best quality, so we take this one - $element = array_values(\array_slice($publicElements, -1))[0]; - - return $element['identifiers'][0]['identifier']; + return $this->getValueForPath('profilepicture'); } - /** - * Helper to extract the preferred locale value from MultiLocaleString - * https://docs.microsoft.com/en-us/linkedin/shared/references/v2/object-types#multilocalestring. - */ - private function getPreferredLocaleValue(string $path): ?string - { - /** @var array> $multiLocaleString */ - $multiLocaleString = $this->getValueForPath($path); - - $locale = ''; - if (isset($multiLocaleString['preferredLocale'])) { - $locale = $multiLocaleString['preferredLocale']['language']; - if (!empty($multiLocaleString['preferredLocale']['country'])) { - $locale .= '_'.$multiLocaleString['preferredLocale']['country']; - } - } - - if (isset($multiLocaleString['localized'][$locale])) { - return $multiLocaleString['localized'][$locale]; - } - - $fallbackLocale = array_keys($multiLocaleString['localized'])[0]; - - return $multiLocaleString['localized'][$fallbackLocale]; - } }