]> git.nothing2do.fr Git - diary-web.git/commitdiff
mistral vibe
authorgaby <gaby@nothing2do.fr>
Mon, 20 Apr 2026 12:07:21 +0000 (14:07 +0200)
committergaby <gaby@nothing2do.fr>
Mon, 20 Apr 2026 12:07:21 +0000 (14:07 +0200)
config/config.php
include/Database.php
include/WebAuthnManager.php
public/index.php
public/login.php
public/register.php

index 9d46fddd249a572e5a9db68ad5dc9c7f145eb51a..634b4362a79921db306710967755fdf0bfb79ee1 100644 (file)
@@ -9,8 +9,10 @@ define('DB_PASS', 'Sr7FEaj2SK');
 
 // Configuration WebAuthn
 define('WEBAUTHN_RP_NAME', 'Diary-web');
-define('WEBAUTHN_RP_ID', parse_url($_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'], PHP_URL_HOST));
-define('WEBAUTHN_ORIGIN', $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST']);
+$rpId = isset($_SERVER['HTTP_HOST']) ? parse_url((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'], PHP_URL_HOST) : 'nothing2do.fr';
+$origin = isset($_SERVER['HTTP_HOST']) ? (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] : 'https://www.nothing2do.fr';
+define('WEBAUTHN_RP_ID', $rpId);
+define('WEBAUTHN_ORIGIN', $origin);
 
 // Initialisation de la base de données
 try {
index e63c0e3662e7ec2d4db479b8a2d187731af50eb5..b90a1af10ec12a40b638234992d44e51c01390bd 100644 (file)
@@ -15,11 +15,25 @@ class Database {
         try {
             // Use the global $db connection from config.php
             global $db;
-            return $db;
+            if ($db instanceof PDO) {
+                return $db;
+            } else {
+                // If global $db is not available, create a new connection
+                $conn = new PDO("pgsql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS);
+                $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+                return $conn;
+            }
         } catch(Exception $exception) {
+            error_log("Erreur de connexion à la base de données : " . $exception->getMessage());
             echo "Erreur de connexion à la base de données : " . $exception->getMessage();
             exit;
         }
     }
+    
+    // Add prepare method for compatibility
+    public function prepare($sql) {
+        $pdo = $this->connect();
+        return $pdo->prepare($sql);
+    }
 }
 ?>
index 3db0d5becd1115b306cd2a863c75b7d40ec2d704..70fbf629ef862c4627e1ea488a6365eda02182b6 100644 (file)
@@ -69,7 +69,10 @@ class WebAuthnManager {
     }
 
     public function register($attestationResponse) {
+        error_log("WebAuthn register called with: " . substr($attestationResponse, 0, 200));
+        
         if (!isset($_SESSION['challenge']) || !isset($_SESSION['username'])) {
+            error_log("WebAuthn register: missing challenge or username in session");
             return false;
         }
 
@@ -79,7 +82,33 @@ class WebAuthnManager {
         unset($_SESSION['username']);
 
         try {
-            $publicKeyCredentialSource = PublicKeyCredentialSource::createFromString($attestationResponse);
+            error_log("WebAuthn register: decoding JSON response");
+            // Decode the JSON response from JavaScript
+            $attestationData = json_decode($attestationResponse, true);
+            
+            if ($attestationData === null) {
+                error_log("WebAuthn register: JSON decode failed. Error: " . json_last_error_msg());
+                return false;
+            }
+            
+            error_log("WebAuthn register: JSON decoded successfully");
+            
+            // Convert base64 back to binary
+            $attestationObject = base64_decode($attestationData['response']['attestationObject']);
+            $clientDataJSON = base64_decode($attestationData['response']['clientDataJSON']);
+            $rawId = base64_decode($attestationData['rawId']);
+            
+            // Create the credential source from the components
+            $publicKeyCredentialSource = PublicKeyCredentialSource::createFromString(
+                json_encode([
+                    'attestationObject' => base64_encode($attestationObject),
+                    'clientDataJSON' => base64_encode($clientDataJSON),
+                    'id' => $attestationData['id'],
+                    'rawId' => base64_encode($rawId),
+                    'type' => $attestationData['type']
+                ])
+            );
+            
             $publicKeyCredential = $publicKeyCredentialSource->getPublicKeyCredential();
 
             if (!$publicKeyCredential->verify($challenge, $this->origin)) {
index 1f4686f1f2eeed5868ad4acb4f2d45caa495b584..8e1d83626e68db3e6e6a31fc8a4eb59831548d10 100644 (file)
@@ -220,7 +220,7 @@ if (empty($triplets)) {
 </head>
 <body>
     <header>
-        <h1>Bienvenue, <?php echo htmlspecialchars($_SESSION['username']); ?></h1>
+        <h1>Bienvenue<?php if (isset($_SESSION['username'])): ?>, <?php echo htmlspecialchars($_SESSION['username']); ?><?php endif; ?></h1>
     </header>
 
     <div id="status-bar">
index 95fd185854caf92de9cbde8028c3123c04ecc717..837b4de053208697039f5e56872fe018e0027c64 100644 (file)
@@ -21,7 +21,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
         $username = trim($_POST['username']);
         
         if (!empty($username)) {
-            $stmt = $pdo->prepare("SELECT user_id, yubikey_id FROM users WHERE username = ?");
+            $stmt = $pdo->prepare("SELECT id, yubikey_id FROM users WHERE username = ?");
             $stmt->execute([$username]);
             $user = $stmt->fetch(PDO::FETCH_ASSOC);
 
@@ -34,7 +34,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                     // Generate authentication options
                     $authenticationOptions = $webAuthnManager->generateAuthenticationOptions();
                     $_SESSION['authentication_username'] = $username;
-                    $_SESSION['authentication_user_id'] = $user['user_id'];
+                    $_SESSION['authentication_user_id'] = $user['id'];
                     $_SESSION['authentication_public_key'] = $yubikey['public_key'];
                     
                     header('Content-Type: application/json');
index a1b872ce1105406d638f75a1308381e71b17266c..67179ebc6abca617b339b49d54acce2f0914c918 100644 (file)
@@ -22,7 +22,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
         
         if (!empty($username)) {
             // Vérifier si le nom d'utilisateur existe déjà
-            $stmt = $pdo->prepare("SELECT user_id FROM users WHERE username = ?");
+            $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
             $stmt->execute([$username]);
             if ($stmt->fetch()) {
                 $error = "Ce nom d'utilisateur est déjà pris.";
@@ -56,17 +56,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                 // Enregistrer l'utilisateur et la YubiKey dans la base de données
                 $pdo->beginTransaction();
                 try {
-                    // Insérer l'utilisateur
-                    $stmt = $pdo->prepare("INSERT INTO users (username) VALUES (?)");
-                    $stmt->execute([$username]);
-                    $userId = $pdo->lastInsertId();
+                    // Insérer l'utilisateur (avec yubikey vide car la colonne est requise)
+                    $stmt = $pdo->prepare("INSERT INTO users (username, yubikey) VALUES (?, ?) RETURNING id");
+                    $stmt->execute([$username, '']); // yubikey vide pour l'instant
+                    $userId = $stmt->fetchColumn();
 
                     // Insérer la YubiKey
                     $stmt = $pdo->prepare("INSERT INTO yubikeys (user_id, key_data, public_key) VALUES (?, ?, ?)");
                     $stmt->execute([$userId, $registrationData['credentialId'], $registrationData['publicKey']]);
 
                     // Mettre à jour l'utilisateur avec l'ID de la YubiKey
-                    $stmt = $pdo->prepare("UPDATE users SET yubikey_id = ? WHERE user_id = ?");
+                    $stmt = $pdo->prepare("UPDATE users SET yubikey_id = ? WHERE id = ?");
                     $stmt->execute([$pdo->lastInsertId(), $userId]);
 
                     $pdo->commit();
@@ -172,6 +172,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
         </form>
         
         <script>
+        // Helper function to convert ArrayBuffer to Base64
+        function arrayBufferToBase64(buffer) {
+            let binary = '';
+            const bytes = new Uint8Array(buffer);
+            const len = bytes.byteLength;
+            for (let i = 0; i < len; i++) {
+                binary += String.fromCharCode(bytes[i]);
+            }
+            return btoa(binary);
+        }
+        
         document.addEventListener('DOMContentLoaded', function() {
             const form = document.getElementById('registrationForm');
             const usernameInput = document.getElementById('username');
@@ -192,7 +203,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                 if (registrationOptions === null) {
                     // Step 1: Get registration options
                     try {
-                        const response = await fetch('register.php', {
+                        const response = await fetch('/diary-web/public/register.php', {
                             method: 'POST',
                             headers: {
                                 'Content-Type': 'application/x-www-form-urlencoded',
@@ -200,23 +211,39 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                             body: `username=${encodeURIComponent(usernameInput.value)}`
                         });
 
-                        const data = await response.json();
+                        const responseText = await response.text();
+                        console.log('Server response (step 1 - username check):', responseText);
+                        console.log('Response length:', responseText.length);
+                        console.log('First 100 chars:', responseText.substring(0, 100));
+                        
+                        try {
+                            const data = JSON.parse(responseText);
 
-                        if (data.success) {
-                            registrationOptions = data.options;
-                            usernameInput.disabled = true;
-                            registerButton.disabled = true;
-                            yubikeySection.style.display = 'block';
-                            webauthnMessage.textContent = 'Prêt pour l\'authentification YubiKey...';
-                            
-                            // Step 2: Call WebAuthn API
-                            await startWebAuthnRegistration();
-                        } else {
-                            alert(data.error || 'Erreur lors de la préparation de l\'inscription');
+                            if (data.success) {
+                                registrationOptions = data.options;
+                                usernameInput.disabled = true;
+                                registerButton.disabled = true;
+                                yubikeySection.style.display = 'block';
+                                webauthnMessage.textContent = 'Prêt pour l\'authentification YubiKey...';
+                                
+                                // Step 2: Call WebAuthn API
+                                await startWebAuthnRegistration();
+                            } else {
+                                alert(data.error || 'Erreur lors de la préparation de l\'inscription');
+                            }
+                        } catch (parseError) {
+                            console.error('JSON parse error:', parseError);
+                            alert('Erreur: Réponse du serveur invalide. Voir console pour détails.');
                         }
                     } catch (error) {
                         console.error('Error:', error);
-                        alert('Erreur lors de la communication avec le serveur');
+                        console.error('Error details:', error.message, error.stack);
+                        try {
+                            console.log('Response text:', await response.text());
+                        } catch (e) {
+                            console.log('Could not get response text');
+                        }
+                        alert('Erreur lors de la communication avec le serveur: ' + error.message);
                     }
                 }
             });
@@ -241,21 +268,42 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
 
                     if (credential) {
                         // Send the attestation response to the server
-                        const response = await fetch('register.php', {
+                        // Convert credential to a format that can be sent to the server
+                        const attestationResponse = {
+                            id: credential.id,
+                            rawId: arrayBufferToBase64(credential.rawId),
+                            response: {
+                                attestationObject: arrayBufferToBase64(credential.response.attestationObject),
+                                clientDataJSON: arrayBufferToBase64(credential.response.clientDataJSON)
+                            },
+                            type: credential.type
+                        };
+                        
+                        const response = await fetch('/diary-web/public/register.php', {
                             method: 'POST',
                             headers: {
                                 'Content-Type': 'application/x-www-form-urlencoded',
                             },
-                            body: `attestationResponse=${encodeURIComponent(JSON.stringify(credential))}`
+                            body: `attestationResponse=${encodeURIComponent(JSON.stringify(attestationResponse))}`
                         });
 
-                        const data = await response.json();
+                        const responseText = await response.text();
+                        console.log('Server response (step 2 - attestation):', responseText);
+                        console.log('Response length:', responseText.length);
+                        console.log('First 100 chars:', responseText.substring(0, 100));
+                        
+                        try {
+                            const data = JSON.parse(responseText);
 
-                        if (data.success) {
-                            webauthnMessage.textContent = 'Inscription réussie ! Redirection...';
-                            window.location.href = data.redirect;
-                        } else {
-                            webauthnMessage.textContent = data.error || 'Erreur lors de l\'inscription';
+                            if (data.success) {
+                                webauthnMessage.textContent = 'Inscription réussie ! Redirection...';
+                                window.location.href = data.redirect;
+                            } else {
+                                webauthnMessage.textContent = data.error || 'Erreur lors de l\'inscription';
+                            }
+                        } catch (parseError) {
+                            console.error('JSON parse error:', parseError);
+                            webauthnMessage.textContent = 'Erreur: Réponse du serveur invalide. Voir console pour détails.';
                             registerButton.disabled = false;
                         }
                     } else {
@@ -264,6 +312,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                     }
                 } catch (error) {
                     console.error('WebAuthn error:', error);
+                    console.error('WebAuthn error details:', error.message, error.stack);
                     webauthnMessage.textContent = 'Erreur YubiKey: ' + error.message;
                     registerButton.disabled = false;
                 }