<?php
// src/Authenticator/XeroAuthenticator.php
namespace App\Authenticator;
use App\Repository\XeroStorageRepository;
use App\String\Constant;
use Doctrine\Persistence\ManagerRegistry;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\GenericProvider;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
class XeroAuthenticator
{
private $provider;
private $requestStack;
private $entityManager;
private $xeroEm;
public function __construct(RequestStack $requestStack, ContainerBagInterface $params,
ManagerRegistry $doctrine, XeroStorageRepository $xeroStorageRepository)
{
$this->provider = new GenericProvider([
'clientId' => $params->get('app.xero_client_id'),
'clientSecret' => $params->get('app.xero_client_secret'),
'redirectUri' => Constant::XERO_REDIRECT_URL,
'urlAuthorize' => Constant::XERO_URL_AUTHORIZE,
'urlAccessToken' => Constant::XERO_URL_ACCESS_TOKEN,
'urlResourceOwnerDetails' => Constant::XERO_URL_RESOURCE,
]);
$this->requestStack = $requestStack;
$this->entityManager = $doctrine->getManager();
$this->xeroEm = $xeroStorageRepository;
}
/**
* Return semantic Xero provider
*
* @return GenericProvider
*/
public function getProvider(): GenericProvider
{
return $this->provider;
}
public function getStorage()
{
// New way of storing storage through DB
$storage = $this->xeroEm->findOneBy(['tag' => 'primary']);
if ($storage){
$xeroTenantId = $storage->getTenantId();
if ($storage->getHasExpired()) {
$newAccessToken = $this->provider->getAccessToken('refresh_token', [
'refresh_token' => $storage->getRefreshToken()
]);
$storage->setAccessToken($newAccessToken->getToken())
->setExpires($newAccessToken->getExpires())
->setTenantId($xeroTenantId)
->setRefreshToken($newAccessToken->getRefreshToken())
->setIdToken($newAccessToken->getValues()["id_token"]);
$this->entityManager->persist($storage);
$this->entityManager->flush();
}
return $storage;
}
return new JsonResponse('Storage is empty', 400);
}
public function authenticate(): Response {
$session = $this->requestStack->getSession();
try {
$options = [
'scope' => ['openid email profile offline_access accounting.settings accounting.transactions accounting.contacts accounting.journals.read accounting.reports.read accounting.attachments']
];
$authorizationUrl = $this->provider->getAuthorizationUrl($options); // get authentication url before getting state
$session->set('oauth2state', $this->provider->getState()); // Set authentication state
return new RedirectResponse($authorizationUrl, 301);
} catch (IdentityProviderException $e) {
return new JsonResponse($e->getMessage(), 400);
}
}
}