revision gestion cookie

This commit is contained in:
2025-09-22 15:17:33 +02:00
parent bcf31c3fbb
commit 0aac7b2c51
7 changed files with 46 additions and 38 deletions

View File

@@ -1,15 +1,11 @@
:80 {
# Force HTTP, désactive auto-HTTPS
# Force HTTP pour le développement
http://localhost {
root * /app/public
php_server
route {
file_server
@php path *.php /index.php
php_fastcgi @php unix//run/php/php-fpm.sock
}
encode gzip
log {
output stdout
}
encode gzip
}
}

View File

@@ -4,6 +4,8 @@ RUN apt-get update && apt-get install -y \
unzip \
&& rm -rf /var/lib/apt/lists/*
RUN cp $PHP_INI_DIR/php.ini-development ./php.ini
# Installe Composer
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
# Installe les extensions PHP nécessaires pour Symfony (pdo_mysql par exemple, si tu utilises MySQL)

View File

@@ -4,11 +4,14 @@ namespace App\Controller;
use App\Form\CodeType;
use App\Hydra\Client;
use App\Hydra\HydraService;
use App\Service\CodeService;
use App\Service\CookieService;
use App\Service\DeviceService;
use App\Service\MailerService;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -17,6 +20,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class MainController extends AbstractController
{
@@ -24,7 +28,9 @@ class MainController extends AbstractController
private readonly CodeService $codeService,
private readonly Client $client,
private readonly CookieService $cookieService,
private readonly MailerService $mailer
private readonly MailerService $mailer,
private readonly UrlGeneratorInterface $router,
private readonly HydraService $hydraService
){
@@ -34,13 +40,12 @@ class MainController extends AbstractController
{
return new Response('<h1>Hello world</h1>');
}
#[Route('/2fa', name: 'app_2fa')]
public function doubleFacteur(Request $request): Response
#[Route('/2fa', name: 'app_2fa', methods: ['GET', 'POST'])]
public function doubleFacteur(Request $request, LoggerInterface $logger): Response
{
$loginChallenge = $request->query->get('loginchallenge');
$identifier = $request->query->get('identifier');
$res = $this->client->fetchLoginRequestInfo($loginChallenge);
$loginRequestInfo = $res->toArray();
if (200 !== $res->getStatusCode()) {
throw new BadRequestException();
}
@@ -50,6 +55,7 @@ class MainController extends AbstractController
'subject' => $identifier,
'remember' => true,
])->toArray();
// dd($loginAcceptRes);
return new RedirectResponse($loginAcceptRes['redirect_to']);
}
@@ -62,22 +68,28 @@ class MainController extends AbstractController
if ($form->isSubmitted() && $form->isValid()){
$cookie = null;
if($form->get('remember_device')){
if($form->get('remember_device')->getData()){
$cookie = $this->cookieService->createCookie($identifier);
}
try{
$loginAcceptRes = $this->client->acceptLoginRequest($loginChallenge, [
'subject' => $identifier,
'remember' => true,
])->toArray();
}catch(ClientException $e){
dump($e);
}
dump($loginAcceptRes);
$response = new RedirectResponse($loginAcceptRes['redirect_to']);
if ($cookie !== null) {
$response->headers->setCookie($cookie);
}
null !== $cookie ?: $response->headers->setCookie($cookie);
return $response;
}
dump('here');
return $this->render('base.html.twig', [
'form'=>$form
]);

View File

@@ -26,7 +26,7 @@ class CodeType extends AbstractType
],
])
->add('remember_device', CheckboxType::class, [
'label'=>('Se souvenir de cet ordinateur'),
'label'=>'Se souvenir de cet ordinateur',
'required'=> false,
'mapped'=>false,
])

View File

@@ -52,10 +52,7 @@ class HydraService extends AbstractController
}
$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' => [
@@ -63,6 +60,7 @@ class HydraService extends AbstractController
],
])->toArray();
dd(vars: $consentAcceptResponse);
return new RedirectResponse($consentAcceptResponse['redirect_to']);
}

View File

@@ -11,30 +11,33 @@ class CookieService
public function __construct(
private readonly ParameterBagInterface $params
){}
private const COOKIE_2FA = 'user_info-2fa';
private const COOKIE_2FA = 'remember_2fa';
public function isValid(Request $request, string $login): bool
{
$cookieValue = $request->cookies->get(self::COOKIE_2FA);
if(!$cookieValue){
return false;
}
[$encodedData, $signature] = explode('.', $cookieValue);
$dataJson = base64_decode($encodedData);
$secret = $this->params->get('kernel.secret');
if (hash_hmac('sha256', $dataJson, $secret) !== $signature) {
return false; // Signature invalide
return false;
}
$data = json_decode($dataJson, true);
if (!$data || $data['login'] !== $login) {
return false; // Login non correspondant
return false;
}
// Recalculer la validité avec la durée paramétrable actuelle
$duration = new \DateInterval($this->params->get('app.2fa_remember_duration')); // ex. P30D
$expirationTime = $data['created_at'] + $duration->format('%s'); // Convertir en secondes
$duration = new \DateInterval($this->params->get('app.2fa_remember_duration'));
$createdAt = (new \DateTimeImmutable())->setTimestamp($data['created_at']);
$expirationTime = $createdAt->add($duration)->getTimestamp();
if (time() > $expirationTime) {
return false; // Expiré selon la durée actuelle
return false;
}
return true;
@@ -63,7 +66,7 @@ class CookieService
->withSecure($this->params->get('kernel.environment') === 'prod')
->withHttpOnly(true)
->withSameSite('Lax')
->withPath('/hydra-otp')
->withPath('/')
;
}
}

View File

@@ -7,9 +7,6 @@
{% block stylesheets %}
{% endblock %}
{% block javascripts %}
{% block importmap %}{{ importmap('app') }}{% endblock %}
{% endblock %}
<style>
body {
display: flex;
@@ -30,8 +27,8 @@
<div syle="">
{{ form_start(form) }}
{{ form_errors(form.code) }}
{{ form_row(form.code) }}
{{ form_row(form.remember_device) }}
{{form_end(form)}}
</div>
{% endblock %}