feat(scheb_2fa): Active Google 2FA et ajoute template de login

Active l'authentification à deux facteurs Google et ajoute un template Twig
pour l
This commit is contained in:
Serreau Jovann
2026-01-16 10:11:07 +01:00
parent 26c3dfd3a1
commit c44d44e4fc
2 changed files with 103 additions and 2 deletions

View File

@@ -1,15 +1,16 @@
# See the configuration reference at https://symfony.com/bundles/SchebTwoFactorBundle/6.x/configuration.html
scheb_two_factor:
security_tokens:
- Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
- Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken
backup_codes:
enabled: true
email:
enabled: true
google:
enabled: true
server_name: "Intranet Ludikevent"
issuer: "Ludikevent"
digits: 6
leeway: 0
template: "security/2fa_login.html.twig"

View File

@@ -0,0 +1,100 @@
{% extends 'base.twig' %}
{% block title %}Vérification Sécurisée - Ludikevent{% endblock %}
{% block body %}
<div class="min-h-screen flex items-center justify-center bg-[#F8FAFC] py-12 px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full bg-white rounded-[2.5rem] p-10 shadow-[0_20px_50px_rgba(0,0,0,0.05)] border border-gray-100 text-center">
{# Logo Ludikevent #}
<div class="flex justify-center mb-8">
<img src="{{ asset('provider/images/logo.png') }}" class="h-50 w-auto" alt="Ludikevent"/>
</div>
{# Icône de sécurité #}
<div class="w-20 h-20 bg-indigo-50 text-indigo-500 rounded-[2rem] flex items-center justify-center mx-auto mb-6 shadow-inner">
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
</div>
<h1 class="text-2xl font-black text-slate-900 uppercase tracking-tighter mb-2">Double Vérification</h1>
{# Sélection du provider si plusieurs sont actifs (ex: Email + Google) #}
{% if availableTwoFactorProviders|length > 1 %}
<p class="text-xs text-slate-400 mb-4 italic">
{{ "choose_provider"|trans({}, 'SchebTwoFactorBundle') }}:
{% for provider in availableTwoFactorProviders %}
<a href="{{ path("2fa_login", {"preferProvider": provider}) }}" class="text-indigo-500 hover:underline font-bold mx-1">{{ provider }}</a>
{% endfor %}
</p>
{% endif %}
<p class="text-slate-400 text-sm mb-8 leading-relaxed">
Saisissez le code de validation {{ twoFactorProvider }} pour confirmer votre identité.
</p>
<form data-turbo="false" class="form" action="{{ checkPathUrl ? checkPathUrl: path(checkPathRoute) }}" method="post">
{# Gestion des erreurs d'authentification #}
{% if authenticationError %}
<div class="mb-6 p-4 bg-rose-50 text-rose-600 text-[11px] font-bold rounded-2xl border border-rose-100 uppercase tracking-widest animate-shake">
{{ authenticationError|trans(authenticationErrorData, 'SchebTwoFactorBundle') }}
</div>
{% endif %}
{# Champ du code #}
<div class="mb-6">
<input type="text"
id="_auth_code"
name="{{ authCodeParameterName }}"
maxlength="6"
required
autofocus
placeholder="· · · · · ·"
inputmode="numeric"
pattern="[0-9]*"
autocomplete="one-time-code"
class="w-full bg-slate-50 border-2 border-transparent focus:border-indigo-500 focus:bg-white focus:ring-0 rounded-2xl py-5 text-center text-4xl font-mono tracking-[0.3em] text-slate-800 transition-all outline-none">
</div>
{# Option "Faire confiance à ce navigateur" #}
{% if displayTrustedOption %}
<div class="flex items-center justify-center mb-8">
<label for="_trusted" class="flex items-center cursor-pointer group">
<input id="_trusted" type="checkbox" name="{{ trustedParameterName }}" class="w-5 h-5 border-gray-200 rounded-lg text-indigo-600 focus:ring-indigo-500 mr-3 transition-all">
<span class="text-xs font-bold text-slate-400 group-hover:text-slate-600 transition-colors uppercase tracking-widest">
{{ "trusted"|trans({}, 'SchebTwoFactorBundle') }}
</span>
</label>
</div>
{% endif %}
{# Protection CSRF #}
{% if isCsrfProtectionEnabled %}
<input type="hidden" name="{{ csrfParameterName }}" value="{{ csrf_token(csrfTokenId) }}">
{% endif %}
<button type="submit" class="w-full py-4 bg-slate-900 hover:bg-indigo-600 text-white rounded-2xl font-bold uppercase text-xs tracking-[0.2em] shadow-xl shadow-slate-200 transition-all transform hover:scale-[1.02] active:scale-[0.98]">
{{ "login"|trans({}, 'SchebTwoFactorBundle') }}
</button>
{# Lien d'annulation / déconnexion #}
<div class="mt-8">
<a href="{{ logoutPath }}" class="text-[10px] font-bold text-slate-300 hover:text-rose-500 transition-colors uppercase tracking-widest">
{{ "cancel"|trans({}, 'SchebTwoFactorBundle') }}
</a>
</div>
</form>
</div>
</div>
<style>
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
.animate-shake { animation: shake 0.2s ease-in-out 0s 2; }
</style>
{% endblock %}