<?php
namespace App\EventListener;
use Psr\Log\LoggerInterface;
use Doctrine\ORM\EntityManagerInterface;
use League\Bundle\OAuth2ServerBundle\Event\AuthorizationRequestResolveEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Routing\RouterInterface;
use App\Entity\User;
use App\Entity\SwitchUserToken;
class AuthorizationRequestResolverListener {
private $symfonyUserKey = 'symfony_username';
private EntityManagerInterface $em;
private LoggerInterface $logger;
private RequestStack $requestStack;
private RouterInterface $router;
private SessionInterface $session;
private TokenStorageInterface $tokenStorage;
private string $oauthImpersonate = "oauth_impersonate_token";
public function __construct(EntityManagerInterface $em, RequestStack $requestStack, RouterInterface $router,
LoggerInterface $logger, TokenStorageInterface $tokenStorage) {
$this->em = $em;
$this->logger = $logger;
$this->requestStack = $requestStack;
$this->router = $router;
$this->session = $this->requestStack->getSession();
$this->tokenStorage = $tokenStorage;
}
public function resolve(AuthorizationRequestResolveEvent $event) {
$user = $this->getUser();
if (empty($user)) {
$this->redirectLogin($event);
} else {
$this->resolveAuthorization($event, $user);
}
}
private function getUser() {
if ($this->session->has($this->oauthImpersonate)) {
return $this->processImpersonate();
}
$token = $this->tokenStorage->getToken();
if (empty($token)) {
return null;
}
return $token->getUser();
}
private function processImpersonate() {
$strToken = $this->session->get($this->oauthImpersonate);
/* @var $token SwitchUserToken */
$token = $this->em->getRepository(SwitchUserToken::class)->findOneBy(array('token' => $strToken));
if (empty($token)) {
return null;
}
if ($token->getUsed()) {
return null;
}
$userID = $token->getUserID();
$user = $this->em->getRepository(User::class)->find($userID);
$token->setUsed(true);
$this->em->persist($token);
$this->em->flush();
$this->session->remove($this->oauthImpersonate);
return $user;
}
private function resolveAuthorization(AuthorizationRequestResolveEvent $event, User $user) {
/* set data for further processing in league oauth2 server */
$event->resolveAuthorization(true);
$event->setUser($user);
/* remove session value */
$this->session->remove($this->symfonyUserKey);
}
private function redirectLogin(AuthorizationRequestResolveEvent $event) {
$request = $this->requestStack->getCurrentRequest();
$parameters = $request->query->all();
$location = $this->router->generate('oauth2_login', $parameters);
$this->logger->info($location);
$redirectResponse = new RedirectResponse($location);
$event->setResponse($redirectResponse);
}
}