2022-12-09 17:31:07 +01:00
< ? php
namespace App\Hydra ;
2024-04-18 17:13:42 +02:00
use App\Entity\User ;
2022-12-09 17:31:07 +01:00
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\Session\SessionInterface ;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface ;
2024-04-18 17:13:42 +02:00
use Symfony\Component\Security\Core\Exception\AccessDeniedException ;
2022-12-09 17:31:07 +01:00
class HydraService extends AbstractController
{
2024-04-18 17:13:42 +02:00
private SessionInterface $session ;
private Client $client ;
private TokenStorageInterface $tokenStorage ;
private string $baseUrl ;
2022-12-09 17:31:07 +01:00
2023-01-06 14:02:20 +01:00
public function __construct ( Client $client , SessionInterface $session , TokenStorageInterface $tokenStorage , string $baseUrl )
2022-12-09 17:31:07 +01:00
{
$this -> session = $session ;
$this -> client = $client ;
$this -> tokenStorage = $tokenStorage ;
2023-01-06 14:02:20 +01:00
$this -> baseUrl = $baseUrl ;
2022-12-09 17:31:07 +01:00
}
2024-04-18 17:13:42 +02:00
public function handleLoginRequest ( Request $request ) : RedirectResponse
2022-12-09 17:31:07 +01:00
{
$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 -> session -> clear ();
2024-04-18 17:13:42 +02:00
throw new BadRequestException ();
2022-12-09 17:31:07 +01:00
}
// 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 -> session -> set ( 'challenge' , $loginRequestInfo [ 'challenge' ]);
2025-03-24 17:20:17 +01:00
return new RedirectResponse ( $this -> baseUrl . '/connect/login-accept' );
2022-12-09 17:31:07 +01:00
}
2024-04-18 17:13:42 +02:00
public function handleConsentRequest ( Request $request ) : RedirectResponse
2022-12-09 17:31:07 +01:00
{
$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 ();
2024-04-18 17:13:42 +02:00
if ( ! $user instanceof User ) {
throw new AccessDeniedException ( 'Utilisateur non autorisé.' );
}
2022-12-09 17:31:07 +01:00
$consentAcceptResponse = $this -> client -> acceptConsentRequest ( $consentRequestInfo [ 'challenge' ], [
'grant_scope' => $consentRequestInfo [ 'requested_scope' ],
'session' => [
'id_token' => $user -> getAttributes (),
],
]) -> toArray ();
return new RedirectResponse ( $consentAcceptResponse [ 'redirect_to' ]);
}
2024-04-18 17:13:42 +02:00
public function handleLogoutRequest ( Request $request ) : RedirectResponse
2022-12-09 17:31:07 +01:00
{
$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 -> session -> clear ();
2022-12-13 15:46:24 +01:00
$this -> tokenStorage -> setToken ( null );
2022-12-09 17:31:07 +01:00
return new RedirectResponse ( $logoutAcceptRes [ 'redirect_to' ]);
}
}