Files
hydra-sql/src/Hydra/HydraService.php
Gauthier DUPONT 0c69082f0e
Some checks failed
Cadoles/hydra-sql/pipeline/head There was a failure building this commit
Cadoles/hydra-sql/pipeline/pr-develop There was a failure building this commit
chore(symfony) #57 : bump symfony to version 6.4 and fix deprecations
2025-07-09 16:47:16 +02:00

81 lines
3.3 KiB
PHP

<?php
namespace App\Hydra;
use App\Entity\User;
use App\Hydra\Exception\InvalidChallengeException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
class HydraService extends AbstractController
{
public function __construct(
private readonly Client $client,
private readonly RequestStack $requestStack,
private readonly TokenStorageInterface $tokenStorage,
private readonly string $baseUrl
){
}
public function handleLoginRequest(Request $request): RedirectResponse
{
$challenge = $request->query->get('login_challenge');
// S'il n'y a pas de challenge, on déclenche une bad request
if (empty($challenge)) {
throw new InvalidChallengeException();
}
// Fetch Hydra login request info
$res = $this->client->fetchLoginRequestInfo($challenge);
$loginRequestInfo = $res->toArray();
if (200 !== $res->getStatusCode()) {
$this->requestStack->getSession()->clear();
throw new BadRequestException();
}
// si le challenge est validé par hydra, on le stocke en session pour l'utiliser par la suite et on redirige vers une route interne protégée qui va déclencher l'identification FranceConnect
$this->requestStack->getSession()->set('challenge', $loginRequestInfo['challenge']);
return new RedirectResponse($this->baseUrl.'/connect/login-accept');
}
public function handleConsentRequest(Request $request): RedirectResponse
{
$challenge = $request->query->get('consent_challenge');
if (!$challenge) {
throw new BadRequestException("Le challenge n'est pas disponible");
}
$consentRequestInfo = $this->client->fetchConsentRequestInfo($challenge)->toArray();
$user = $this->getUser();
if (!$user instanceof User) {
throw new AccessDeniedException('Utilisateur non autorisé.');
}
$consentAcceptResponse = $this->client->acceptConsentRequest($consentRequestInfo['challenge'], [
'grant_scope' => $consentRequestInfo['requested_scope'],
'session' => [
'id_token' => $user->getAttributes(),
],
])->toArray();
return new RedirectResponse($consentAcceptResponse['redirect_to']);
}
public function handleLogoutRequest(Request $request): RedirectResponse
{
$logoutChallenge = $request->get('logout_challenge');
if (empty($logoutChallenge)) {
throw new InvalidChallengeException();
}
$logoutRequestInfo = $this->client->fetchLogoutRequestInfo($logoutChallenge)->toArray();
$logoutAcceptRes = $this->client->acceptLogoutRequest($logoutRequestInfo['challenge'])->toArray();
$this->requestStack->getSession()->clear();
$this->tokenStorage->setToken(null);
return new RedirectResponse($logoutAcceptRes['redirect_to']);
}
}