2024-07-22 02:17:42 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Security;
|
|
|
|
|
|
|
|
|
|
use App\Entity\User;
|
|
|
|
|
use App\Repository\UserRepository;
|
|
|
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
|
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
|
|
|
|
|
use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
|
2024-07-23 13:31:45 +02:00
|
|
|
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
|
|
|
|
|
use Symfony\Component\HttpFoundation\Cookie;
|
2024-07-22 02:17:42 +02:00
|
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
|
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
|
use Symfony\Component\Routing\RouterInterface;
|
|
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
|
|
|
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
|
|
|
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
|
|
|
|
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
|
|
|
|
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
|
|
|
|
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
|
|
|
|
|
2024-08-02 23:24:52 +02:00
|
|
|
class OAuthAuthenticator extends OAuth2Authenticator implements AuthenticationEntryPointInterface
|
2024-07-22 02:17:42 +02:00
|
|
|
{
|
|
|
|
|
public function __construct(
|
2024-08-02 23:24:52 +02:00
|
|
|
private readonly ClientRegistry $clientRegistry,
|
|
|
|
|
private readonly UserRepository $userRepository,
|
|
|
|
|
private readonly EntityManagerInterface $em,
|
|
|
|
|
private readonly RouterInterface $router,
|
2024-07-23 13:31:45 +02:00
|
|
|
private readonly JWTTokenManagerInterface $JWTManager
|
2024-08-02 23:24:52 +02:00
|
|
|
) {
|
2024-07-22 02:17:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called on every request to decide if this authenticator should be
|
|
|
|
|
* used for the request. Returning `false` will cause this authenticator
|
|
|
|
|
* to be skipped.
|
|
|
|
|
*/
|
|
|
|
|
public function supports(Request $request): ?bool
|
|
|
|
|
{
|
2024-08-02 23:24:52 +02:00
|
|
|
return 'oauth_connect_check' === $request->attributes->get('_route');
|
2024-07-22 02:17:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function authenticate(Request $request): Passport
|
|
|
|
|
{
|
|
|
|
|
$client = $this->clientRegistry->getClient('oauth');
|
|
|
|
|
$accessToken = $this->fetchAccessToken($client);
|
|
|
|
|
|
|
|
|
|
return new SelfValidatingPassport(
|
|
|
|
|
new UserBadge($accessToken->getToken(), function () use ($accessToken, $client) {
|
|
|
|
|
/** @var OAuthResourceOwner $userFromToken */
|
|
|
|
|
$userFromToken = $client->fetchUserFromToken($accessToken);
|
|
|
|
|
|
|
|
|
|
$existingUser = $this->userRepository->findOneBy(['email' => $userFromToken->getEmail()]);
|
|
|
|
|
|
2024-08-02 23:24:52 +02:00
|
|
|
if ($existingUser) {
|
|
|
|
|
return $existingUser;
|
|
|
|
|
}
|
2024-07-22 02:17:42 +02:00
|
|
|
|
|
|
|
|
$user = new User();
|
2024-08-05 01:30:27 +02:00
|
|
|
$user->setEmail($userFromToken->getEmail())->setVerified(true);
|
2024-07-22 02:17:42 +02:00
|
|
|
$this->em->persist($user);
|
|
|
|
|
$this->em->flush();
|
|
|
|
|
|
|
|
|
|
return $user;
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): RedirectResponse
|
|
|
|
|
{
|
2024-07-23 13:31:45 +02:00
|
|
|
$token = $this->JWTManager->create($token->getUser());
|
|
|
|
|
$response = new RedirectResponse($this->router->generate('index'));
|
|
|
|
|
$response->headers->setCookie(
|
|
|
|
|
new Cookie(
|
|
|
|
|
'BEARER',
|
|
|
|
|
$token,
|
2024-08-05 19:03:47 +02:00
|
|
|
time() + 7200, // expiration
|
2024-07-23 13:31:45 +02:00
|
|
|
'/',
|
|
|
|
|
null,
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
'strict'
|
|
|
|
|
)
|
|
|
|
|
);
|
2024-08-02 23:24:52 +02:00
|
|
|
|
2024-07-23 13:31:45 +02:00
|
|
|
return $response;
|
2024-07-22 02:17:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
|
|
|
|
{
|
|
|
|
|
$message = strtr($exception->getMessageKey(), $exception->getMessageData());
|
|
|
|
|
|
|
|
|
|
return new Response($message, Response::HTTP_UNAUTHORIZED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function start(Request $request, ?AuthenticationException $authException = null): Response
|
|
|
|
|
{
|
|
|
|
|
return new RedirectResponse(
|
|
|
|
|
'/login/oauth',
|
|
|
|
|
Response::HTTP_TEMPORARY_REDIRECT
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|