<?php
namespace App\Security;
use KnpU\OAuth2ClientBundle\Client\Provider\KeycloakClient;
use KnpU\OAuth2ClientBundle\Security\Authenticator\SocialAuthenticator;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* Class KeycloakAuthenticator
*/
class KeycloakAuthenticator extends SocialAuthenticator
{
private $clientRegistry;
private $router;
public function __construct(ClientRegistry $clientRegistry, RouterInterface $router)
{
$this->clientRegistry = $clientRegistry;
$this->router = $router;
}
public function start(Request $request, AuthenticationException $authException = null)
{
$connectUrl = $this->router->generate('connect_keycloak');
return new RedirectResponse(
$connectUrl, // might be the site, where users choose their oauth provider
Response::HTTP_TEMPORARY_REDIRECT
);
}
public function supports(Request $request)
{
return $request->attributes->get('_route') === 'connect_auth_check';
}
public function getCredentials(Request $request)
{
$accessToken = $this->fetchAccessToken($this->getKeycloakClient());
$this->setTokenToSession($request, $accessToken);
return $accessToken;
}
private function setTokenToSession(Request $request, $credentials){
$session = $request->getSession();
$session->set('access_token', $credentials);
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$keycloakUser = $this->getKeycloakClient()->fetchUserFromToken($credentials);
$responseArray = $keycloakUser->toArray();
$user = new User();
$user->setKeycloakId($keycloakUser->getId());
$user->setEmail($keycloakUser->getEmail());
if (isset($responseArray['gender'])) {
$user->setGenre($responseArray['gender']);
}
$user->setPrenom($responseArray['given_name']);
$user->setNom($responseArray['family_name']);
$tabRole = ['ROLE_USER'];
foreach ($keycloakUser->toArray()['roles'] as $role) {
$tabRole[] = "ROLE_" . $role;
}
$user->setRoles($tabRole);
return $user;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$session = $request->getSession();
$path = $session->get('path');
$targetUrl = $path;
if($path == null){
$targetUrl = $request->getSchemeAndHttpHost();
}
//$targetUrl = $this->router->generate($path);
// retirer la session, pour éviter d'itérer à l'intérieur du silentAuthenticator.
$session->clear();
// ajouter dans la session le fait que l'utilisateur n'est pas authentifié.
$session->set('unauthentified', true);
$session->set('path', $path);
return new RedirectResponse($targetUrl);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
{
$session = $request->getSession();
$session->remove('unauthentified');
$targetUrl = $request->getSession()->get('_security.'.$providerKey.'.target_path');
if($targetUrl == null){
$targetUrl = urldecode($session->get('path'));
}
if ($targetUrl == null) {
$targetUrl = $request->getSchemeAndHttpHost();
}
return new RedirectResponse($targetUrl);
}
/**
* @return KeycloakClient
*/
private function getKeycloakClient()
{
return $this->clientRegistry->getClient('keycloak');
}
}