Files
2025-05-12 15:45:02 +08:00

91 lines
2.4 KiB
PHP

<?php
namespace Overtrue\Socialite\Providers;
use JetBrains\PhpStorm\ArrayShape;
use JetBrains\PhpStorm\Pure;
use Overtrue\Socialite\Contracts;
use Overtrue\Socialite\User;
class GitHub extends Base
{
public const NAME = 'github';
protected array $scopes = ['read:user'];
protected string $scopeSeparator = ' ';
protected function getAuthUrl(): string
{
return $this->buildAuthUrlFromBase('https://github.com/login/oauth/authorize');
}
protected function getTokenUrl(): string
{
return 'https://github.com/login/oauth/access_token';
}
protected function getUserByToken(string $token): array
{
$userUrl = 'https://api.github.com/user';
$response = $this->getHttpClient()->get(
$userUrl,
$this->createAuthorizationHeaders($token)
);
$user = $this->fromJsonBody($response);
if (\in_array('user:email', $this->scopes)) {
$user[Contracts\ABNF_EMAIL] = $this->getEmailByToken($token);
}
return $user;
}
protected function getEmailByToken(string $token): string
{
$emailsUrl = 'https://api.github.com/user/emails';
try {
$response = $this->getHttpClient()->get(
$emailsUrl,
$this->createAuthorizationHeaders($token)
);
} catch (\Throwable $e) {
return '';
}
foreach ($this->fromJsonBody($response) as $email) {
if ($email['primary'] && $email['verified']) {
return $email[Contracts\ABNF_EMAIL];
}
}
return '';
}
#[Pure]
protected function mapUserToObject(array $user): Contracts\UserInterface
{
return new User([
Contracts\ABNF_ID => $user[Contracts\ABNF_ID] ?? null,
Contracts\ABNF_NICKNAME => $user['login'] ?? null,
Contracts\ABNF_NAME => $user[Contracts\ABNF_NAME] ?? null,
Contracts\ABNF_EMAIL => $user[Contracts\ABNF_EMAIL] ?? null,
Contracts\ABNF_AVATAR => $user['avatar_url'] ?? null,
]);
}
#[ArrayShape(['headers' => 'array'])]
protected function createAuthorizationHeaders(string $token): array
{
return [
'headers' => [
'Accept' => 'application/vnd.github.v3+json',
'Authorization' => \sprintf('token %s', $token),
],
];
}
}