Browse Source

feat(authenticator): Ajoute la gestion de l'authentification Google et améliore la soumission du formulaire

stany.ferer 2 weeks ago
parent
commit
ba5135a614

+ 25 - 2
core/class/securityHeaders.class.php

@@ -47,7 +47,8 @@ class securityHeaders
             self::setReferrerPolicy();
         }
 
-        if ($options['hsts'] && self::isHTTPS()) {
+        // HSTS uniquement en production (pas en DEV)
+        if ($options['hsts'] && self::isHTTPS() && !self::isDevEnvironment()) {
             self::setHSTS();
         }
 
@@ -75,7 +76,8 @@ class securityHeaders
         self::setXSSProtection();
         self::setReferrerPolicy('no-referrer');
 
-        if (self::isHTTPS()) {
+        // HSTS uniquement en production (pas en DEV pour éviter les problèmes de certificat local)
+        if (self::isHTTPS() && !self::isDevEnvironment()) {
             self::setHSTS();
         }
 
@@ -261,6 +263,27 @@ class securityHeaders
         return false;
     }
 
+    /**
+     * Vérifie si on est en environnement de développement
+     * 
+     * @return bool
+     */
+    private static function isDevEnvironment(): bool
+    {
+        // Vérifier la constante ENVIRONNEMENT
+        if (defined('ENVIRONNEMENT') && ENVIRONNEMENT === 'DEV') {
+            return true;
+        }
+
+        // Vérifier les domaines locaux
+        $host = $_SERVER['HTTP_HOST'] ?? '';
+        if (strpos($host, 'local.') === 0 || strpos($host, 'localhost') !== false || strpos($host, '127.0.0.1') !== false) {
+            return true;
+        }
+
+        return false;
+    }
+
     /**
      * Applique les headers de sécurité pour les API JSON
      */

+ 11 - 4
core/submit/cms.authenticator.php

@@ -1,4 +1,11 @@
-<?php 
-if (core::ifPost("from") AND core::getPost("from") == "authenticator") {
-    echo user::checkGoogleAuthenticator(core::getPost("email"));
-}
+<?php
+if (core::ifPost("from") and core::getPost("from") == "authenticator") {
+    $result = user::checkGoogleAuthenticator(core::getPost("email"));
+
+    // Retourner du JSON valide pour la requête AJAX
+    header('Content-Type: application/json');
+    echo json_encode([
+        'authenticator' => (int)$result,
+        'required' => ($result == 1)
+    ]);
+}

+ 33 - 10
core/views/pages/cms.login.php

@@ -69,6 +69,9 @@ securityHeaders::applyForLogin();
 
             <script nonce="<?php echo securityHeaders::getNonce(); ?>">
                 $(document).ready(function() {
+                    // Variable pour savoir si on attend le code Authenticator
+                    var authenticatorRequired = false;
+                    
                     // Configuration CSRF pour les requêtes AJAX
                     $(document).ajaxSend(function(event, jqxhr, settings) {
                         if (settings.type === 'POST') {
@@ -79,10 +82,20 @@ securityHeaders::applyForLogin();
                         }
                     });
 
-                    $("#submit-authent").on("click", function() {
+                    $("#submit-authent").on("click", function(e) {
                         var $btn = $(this);
                         var $warning = $("#rate-limit-warning");
 
+                        // Si Authenticator est requis et le code est rempli, soumettre le formulaire
+                        if (authenticatorRequired) {
+                            if ($("#authenticator").val().length === 6) {
+                                $("#form-authent").submit();
+                            } else {
+                                $warning.html('<strong>⚠️ Veuillez entrer le code à 6 chiffres.</strong>').show();
+                            }
+                            return;
+                        }
+
                         // Désactiver le bouton pendant la requête
                         $btn.prop('disabled', true).val('Vérification...');
                         $warning.hide();
@@ -90,7 +103,7 @@ securityHeaders::applyForLogin();
                         var formData = {
                             email: $("#email").val(),
                             from: "authenticator",
-                            csrf_token: $("input[name='csrf_token']").val() // Inclure le token CSRF du formulaire
+                            csrf_token: $("input[name='csrf_token']").val()
                         };
 
                         $.ajax({
@@ -98,32 +111,34 @@ securityHeaders::applyForLogin();
                             url: "submit.php",
                             data: formData,
                             dataType: "json",
-                            encode: true,
+                            xhrFields: {
+                                withCredentials: true
+                            },
                         }).done(function(data) {
+                            console.log("Réponse authenticator:", data);
                             if (data && data.blocked) {
-                                // Compte bloqué - afficher le message
                                 $warning.html('<strong>⚠️ ' + data.message + '</strong>').show();
                                 $btn.prop('disabled', true).val('Bloqué');
-                                // Réactiver après le délai
                                 if (data.remaining_time) {
                                     setTimeout(function() {
                                         $btn.prop('disabled', false).val('Se connecter');
                                         $warning.hide();
                                     }, data.remaining_time * 1000);
                                 }
-                            } else if (data == 1 || data.authenticator == 1) {
-                                $("#authenticator").show();
+                            } else if (data && (data.authenticator == 1 || data.required === true)) {
+                                // Google Authenticator requis
+                                authenticatorRequired = true;
+                                $("#authenticator").show().focus();
                                 $("#authenticator").prop("required", true);
-                                $('#submit-authent').attr('type', 'submit').val('Se connecter');
-                                $btn.prop('disabled', false);
+                                $btn.prop('disabled', false).val('Valider');
                             } else {
+                                // Pas de 2FA, soumettre directement
                                 $("#form-authent").submit();
                             }
                         }).fail(function(jqXHR, textStatus, errorThrown) {
                             console.error("Erreur AJAX:", textStatus, errorThrown);
                             $btn.prop('disabled', false).val('Se connecter');
 
-                            // Gérer les erreurs spécifiques
                             if (jqXHR.status === 429) {
                                 var response = jqXHR.responseJSON || {};
                                 $warning.html('<strong>⚠️ ' + (response.message || 'Trop de tentatives. Veuillez patienter.') + '</strong>').show();
@@ -132,6 +147,14 @@ securityHeaders::applyForLogin();
                             }
                         });
                     });
+                    
+                    // Permettre la soumission avec Entrée dans le champ Authenticator
+                    $("#authenticator").on("keypress", function(e) {
+                        if (e.which === 13 && $(this).val().length === 6) {
+                            e.preventDefault();
+                            $("#form-authent").submit();
+                        }
+                    });
                 });
             </script>
         </div>