diff --git a/src/Libraries/GithubOAuth.php b/src/Libraries/GithubOAuth.php index f317be7..4342e37 100644 --- a/src/Libraries/GithubOAuth.php +++ b/src/Libraries/GithubOAuth.php @@ -21,10 +21,12 @@ class GithubOAuth extends AbstractOAuth { - public static string $API_CODE_URL = 'https://github.com/login/oauth/authorize'; - public static string $API_TOKEN_URL = 'https://github.com/login/oauth/access_token'; - public static string $API_USER_INFO_URL = 'https://api.github.com/user'; - private static string $APPLICATION_NAME = 'ShieldOAuth'; + public static string $API_CODE_URL = 'https://github.com/login/oauth/authorize'; + public static string $API_TOKEN_URL = 'https://github.com/login/oauth/access_token'; + public static string $API_USER_INFO_URL = 'https://api.github.com/user'; // The /user API returns the user's publicly visible data or null for those that are not set + public static string $API_USER_EMAILS_URL = 'https://api.github.com/user/emails'; // The /user/emails API returns all email addresses for the user, including those that are not set public + private static string $APPLICATION_NAME = 'ShieldOAuth'; + protected string $token; protected CURLRequest $client; protected ShieldOAuthConfig $config; @@ -89,7 +91,49 @@ protected function fetchUserInfoWithToken(): object exit($e->getMessage()); } - return json_decode($response->getBody()); + $userInfo = json_decode($response->getBody(), false); + + // the email address is mandatory + if (empty($userInfo->email)) { + $userInfo->email = $this->getUserPrimaryEmail($this->fetchUserEmailsWithToken()); + } + + return $userInfo; + } + + /** + * @return list + */ + protected function fetchUserEmailsWithToken(): array + { + // send request to API URL + try { + $response = $this->client->request('GET', self::$API_USER_EMAILS_URL, [ + 'headers' => [ + 'User-Agent' => self::$APPLICATION_NAME . '/1.0', + 'Accept' => 'application/vnd.github+json', + 'Authorization' => 'Bearer ' . $this->getToken(), + ], + 'http_errors' => false, + ]); + } catch (Exception $e) { + exit($e->getMessage()); + } + + return json_decode($response->getBody(), false); + } + + /** + * @param list $emailAddresses + */ + protected function getUserPrimaryEmail(array $emailAddresses): string + { + // try to get the one marked as primary, otherwise grab the first one + if (! empty($emailAddresses)) { + $primaryEmail = array_filter($emailAddresses, static fn ($eMail) => $eMail->primary); + $userEmail = ! empty($primaryEmail) ? array_shift($primaryEmail)->email : array_shift($emailAddresses)->email; + } + return $userEmail ?? ''; } protected function setColumnsName(string $nameOfProcess, $userInfo): array