64 lines
2.1 KiB
PHP
64 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Enums\SocialProvider;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use Illuminate\Support\Arr;
|
|
use Laravel\Socialite\Contracts\Factory as SocialiteFactory;
|
|
use Laravel\Socialite\Contracts\User as SocialiteUser;
|
|
use Laravel\Socialite\Two\AbstractProvider;
|
|
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
|
use Throwable;
|
|
|
|
class SocialIdentityResolver
|
|
{
|
|
public function __construct(
|
|
private SocialiteFactory $socialite,
|
|
private AppleIdentityTokenVerifier $appleIdentityTokenVerifier,
|
|
private SocialAuthenticationNonce $socialAuthenticationNonce,
|
|
) {}
|
|
|
|
public function resolve(SocialProvider $provider, string $identityToken, ?string $nonce): SocialiteUser
|
|
{
|
|
try {
|
|
return match ($provider) {
|
|
SocialProvider::Google => $this->googleUserFromToken($identityToken, $nonce ?? ''),
|
|
SocialProvider::Apple => $this->appleIdentityTokenVerifier->userFromToken(
|
|
$identityToken,
|
|
$nonce ?? '',
|
|
),
|
|
};
|
|
} catch (HttpExceptionInterface $exception) {
|
|
throw $exception;
|
|
} catch (GuzzleException) {
|
|
abort(503, 'SOCIAL_PROVIDER_UNAVAILABLE');
|
|
} catch (Throwable) {
|
|
abort(401, 'SOCIAL_TOKEN_INVALID');
|
|
}
|
|
}
|
|
|
|
private function googleUserFromToken(string $identityToken, string $nonce): SocialiteUser
|
|
{
|
|
if (! config('services.google.client_id')) {
|
|
abort(503, 'SOCIAL_PROVIDER_NOT_CONFIGURED');
|
|
}
|
|
|
|
/** @var AbstractProvider $provider */
|
|
$provider = $this->socialite->driver(SocialProvider::Google->value);
|
|
|
|
$identity = $provider->userFromToken($identityToken);
|
|
$rawIdentity = method_exists($identity, 'getRaw') ? $identity->getRaw() : [];
|
|
|
|
if (! is_array($rawIdentity) || ! $this->socialAuthenticationNonce->consume(
|
|
SocialProvider::Google,
|
|
$nonce,
|
|
Arr::get($rawIdentity, 'nonce'),
|
|
)) {
|
|
abort(401, 'SOCIAL_TOKEN_INVALID');
|
|
}
|
|
|
|
return $identity;
|
|
}
|
|
}
|