Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
declare(strict_types=1);
namespace App\Controller\Back\Oauth;
use App\Core\Authentication\Domain\Oauth2;
use App\Core\Authentication\Domain\Repository\Oauth2RepositoryInterface;
use App\Core\Authentication\Infra\Service\LoginFormAuthenticator;
use App\Core\Authentication\Infra\Service\OauthQueryExtractorRegistry;
use App\Core\Authentication\Infra\Service\OauthUrlBuilderRegistry;
use App\Core\User\Domain\BaseUser;
use App\Core\User\Domain\Repository\BaseUserRepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class OauthRedirectController extends AbstractController
{
/** @var AdapterInterface */
private $cache;
/** @var BaseUserRepositoryInterface */
private $baseUserRepository;
/** @var HttpClientInterface */
private $httpClient;
/** @var OauthQueryExtractorRegistry */
private $queryExtractorRegistry;
/** @var OauthUrlBuilderRegistry */
private $oauthUrlBuilderRegistry;
/** @var Oauth2RepositoryInterface */
private $repository;
/** @var GuardAuthenticatorHandler */
private $guardAuthenticatorHandler;
/** @var LoginFormAuthenticator */
private $loginFormAuthenticator;
public function __construct(
AdapterInterface $cache,
BaseUserRepositoryInterface $baseUserRepository,
HttpClientInterface $httpClient,
OauthQueryExtractorRegistry $queryExtractorRegistry,
OauthUrlBuilderRegistry $oauthUrlBuilderRegistry,
Oauth2RepositoryInterface $repository,
GuardAuthenticatorHandler $guardAuthenticatorHandler,
LoginFormAuthenticator $loginFormAuthenticator
){
$this->cache = $cache;
$this->baseUserRepository = $baseUserRepository;
$this->httpClient = $httpClient;
$this->queryExtractorRegistry = $queryExtractorRegistry;
$this->oauthUrlBuilderRegistry = $oauthUrlBuilderRegistry;
$this->repository = $repository;
$this->guardAuthenticatorHandler = $guardAuthenticatorHandler;
$this->loginFormAuthenticator = $loginFormAuthenticator;
}
public function __invoke(Request $request)
{
$state = $request->get('state');
$Oauth2 = $this->repository->findOneBy([
'state' => $state
]);
if($Oauth2 instanceof Oauth2){
// extract auth code
$extractor = $this->queryExtractorRegistry->getExtractorFor($Oauth2->getProvider());
/** @var Oauth2 $Oauth2 */
$Oauth2 = $extractor->extractAuthorizeRedirect($request);
// request access token
$urlBuilder = $this->oauthUrlBuilderRegistry->getBuilderFor($Oauth2->getProvider());
$httpRequest = $urlBuilder->requestToken($Oauth2);
$httpResponse = $this->httpClient->request($httpRequest->getMethod(), $httpRequest->getUrl());
// extract access token
if($httpResponse->getStatusCode() < 299){
$responseContent = json_decode($httpResponse->getContent(), true);
$Oauth2 = $extractor->extractTokenResponse($responseContent, $Oauth2);
$this->repository->save($Oauth2);
}
// inspect token
$appToken = $this->getAppToken($urlBuilder, $extractor, $Oauth2);
$httpRequest = $urlBuilder->inspectToken($Oauth2, $appToken);
$httpResponse = $this->httpClient->request($httpRequest->getMethod(), $httpRequest->getUrl());
if($httpResponse->getStatusCode() < 299) {
$responseContent = json_decode($httpResponse->getContent(), true);
$Oauth2 = $extractor->extractInspectResponse($responseContent, $Oauth2);
$this->repository->save($Oauth2);
}
// request user info
$httpRequest = $urlBuilder->userInformation($Oauth2);
$httpResponse = $this->httpClient->request($httpRequest->getMethod(), $httpRequest->getUrl());
if($httpResponse->getStatusCode() < 299) {
$responseContent = json_decode($httpResponse->getContent(), true);
$Oauth2 = $extractor->extractUserData($responseContent, $Oauth2);
$this->repository->save($Oauth2);
}
$user = $this->baseUserRepository->findOneBy([
'username' => $Oauth2->getEmail()
]);
if(!$user instanceof BaseUser){
throw new UsernameNotFoundException("Impossible d'authentifier l'utilisateur");
}
return $this->guardAuthenticatorHandler->authenticateUserAndHandleSuccess(
$user,
$request,
$this->loginFormAuthenticator,
'main'
);
}
return new RedirectResponse('/', 302);
}
private function getAppToken($urlBuilder, $extractor, $Oauth2)
{
$item = $this->cache->getItem($Oauth2->getProvider().'AppToken');
if(!$item->isHit()){
$url = $urlBuilder->getAppToken();
$response = $this->httpClient->request('GET', $url);
$responseContent = json_decode($response->getContent(), true);
$token = $extractor->extractAppToken($responseContent);
$item->set($token);
$this->cache->save($item);
}
return $item->get();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.