// config/config.php
// Configuration de la base de données PostgreSQL
-define('DB_HOST', 'postgresql-nothing2do.eu.alwaysdata.net');
-define('DB_NAME', 'nothing2do.eu_diary');
-define('DB_USER', 'nothing2do.eu');
-define('DB_PASS', 'Sr7FEaj2SK');
+define('DB_HOST', 'localhost');
+define('DB_NAME', 'diary');
+define('DB_USER', 'user');
+define('DB_PASS', 'password');
// Configuration WebAuthn
define('WEBAUTHN_RP_NAME', 'Diary-web');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Vérification et création des tables si elles n'existent pas
- $db->exec("
- CREATE TABLE IF NOT EXISTS users (
- user_id SERIAL PRIMARY KEY,
- username VARCHAR(255) NOT NULL UNIQUE,
- yubikey_id INT UNIQUE,
- FOREIGN KEY (yubikey_id) REFERENCES yubikeys(yubikey_id) ON DELETE SET NULL
+ // On supprime les contraintes de clé étrangère pour éviter les erreurs de permissions
+ try {
+ $db->exec(
+ "CREATE TABLE IF NOT EXISTS users (
+ user_id SERIAL PRIMARY KEY,
+ username VARCHAR(255) NOT NULL UNIQUE,
+ yubikey_id INT UNIQUE
+ );"
);
-
- CREATE TABLE IF NOT EXISTS yubikeys (
- yubikey_id SERIAL PRIMARY KEY,
- user_id INT UNIQUE,
- key_data TEXT NOT NULL,
- public_key TEXT NOT NULL,
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
+
+ $db->exec(
+ "CREATE TABLE IF NOT EXISTS yubikeys (
+ yubikey_id SERIAL PRIMARY KEY,
+ user_id INT UNIQUE,
+ key_data TEXT NOT NULL,
+ public_key TEXT NOT NULL
+ );"
);
-
- CREATE TABLE IF NOT EXISTS triplets (
- triplet_id SERIAL PRIMARY KEY,
- user_id INT NOT NULL,
- label VARCHAR(255) NOT NULL,
- keyword VARCHAR(255) NOT NULL,
- action VARCHAR(255) NOT NULL,
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
+
+ $db->exec(
+ "CREATE TABLE IF NOT EXISTS triplets (
+ triplet_id SERIAL PRIMARY KEY,
+ user_id INT NOT NULL,
+ label VARCHAR(255) NOT NULL,
+ keyword VARCHAR(255) NOT NULL,
+ action VARCHAR(255) NOT NULL
+ );"
);
-
- CREATE INDEX IF NOT EXISTS idx_triplets_user_id ON triplets(user_id);
- CREATE INDEX IF NOT EXISTS idx_yubikeys_user_id ON yubikeys(user_id);
- ");
+
+ $db->exec("CREATE INDEX IF NOT EXISTS idx_triplets_user_id ON triplets(user_id);");
+ $db->exec("CREATE INDEX IF NOT EXISTS idx_yubikeys_user_id ON yubikeys(user_id);");
+ } catch (PDOException $e) {
+ // Ignorer les erreurs de création de tables si elles existent déjà
+ // ou si l'utilisateur n'a pas les permissions nécessaires
+ error_log("Warning: Could not create tables: " . $e->getMessage());
+ }
} catch (PDOException $e) {
die("Erreur de connexion ou d'initialisation de la base de données : " . $e->getMessage());
}
-?>
+?>
\ No newline at end of file
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
+ // Check if user has a YubiKey registered
$stmt = $pdo->prepare("SELECT key_data, public_key FROM yubikeys WHERE yubikey_id = ?");
$stmt->execute([$user['yubikey_id']]);
$yubikey = $stmt->fetch(PDO::FETCH_ASSOC);
if ($yubikey) {
- // Generate authentication options
+ // User has a YubiKey, proceed with WebAuthn authentication
$authenticationOptions = $webAuthnManager->generateAuthenticationOptions();
$_SESSION['authentication_username'] = $username;
$_SESSION['authentication_user_id'] = $user['id'];
'options' => $authenticationOptions->jsonSerialize()
]);
exit();
+ } else {
+ // User exists but has no YubiKey registered
+ // For now, we'll still require YubiKey registration
+ // You might want to implement alternative authentication here
+ header('Content-Type: application/json');
+ echo json_encode(['success' => false, 'error' => 'Aucune YubiKey enregistrée pour cet utilisateur. Veuillez vous inscrire d\'abord.']);
+ exit();
}
}
header('Content-Type: application/json');
- echo json_encode(['success' => false, 'error' => 'Nom d\'utilisateur ou YubiKey invalide.']);
+ echo json_encode(['success' => false, 'error' => 'Nom d\'utilisateur invalide.']);
exit();
}
} elseif (isset($_POST['assertionResponse'])) {
// Traitement du formulaire d'inscription
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ error_log("Register.php: POST request received");
+
if (isset($_POST['username'])) {
// Step 1: Generate registration options
$username = trim($_POST['username']);
+ error_log("Register.php: Username received: " . $username);
if (!empty($username)) {
// Vérifier si le nom d'utilisateur existe déjà
$stmt->execute([$username]);
if ($stmt->fetch()) {
$error = "Ce nom d'utilisateur est déjà pris.";
+ error_log("Register.php: Username already taken");
} else {
// Generate WebAuthn registration options
+ error_log("Register.php: Generating registration options");
$registrationOptions = $webAuthnManager->generateRegistrationOptions($username);
$_SESSION['registration_options'] = $registrationOptions;
$_SESSION['registration_username'] = $username;
'success' => true,
'options' => $registrationOptions->jsonSerialize()
]);
+ error_log("Register.php: Registration options sent");
exit();
}
}
} elseif (isset($_POST['attestationResponse'])) {
+ error_log("Register.php: Attestation response received");
// Step 2: Process the attestation response
$attestationResponse = trim($_POST['attestationResponse']);
$registrationData = $webAuthnManager->register($attestationResponse);
if ($registrationData) {
- // Enregistrer l'utilisateur et la YubiKey dans la base de données
+ // Enregistrer l'utilisateur et les informations WebAuthn dans la base de données
$pdo->beginTransaction();
try {
- // 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
+ // Insérer l'utilisateur
+ $stmt = $pdo->prepare("INSERT INTO users (username) VALUES (?) RETURNING id");
+ $stmt->execute([$username]);
$userId = $stmt->fetchColumn();
- // Insérer la YubiKey
+ // Insérer les informations WebAuthn (anciennement 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
+ // Mettre à jour l'utilisateur avec l'ID des informations WebAuthn
$stmt = $pdo->prepare("UPDATE users SET yubikey_id = ? WHERE id = ?");
$stmt->execute([$pdo->lastInsertId(), $userId]);
}
} else {
header('Content-Type: application/json');
- echo json_encode(['success' => false, 'error' => "La réponse YubiKey est invalide."]);
+ echo json_encode(['success' => false, 'error' => "La réponse WebAuthn est invalide."]);
exit();
}
}
<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]);
+ try {
+ const bytes = new Uint8Array(buffer);
+ let binary = '';
+ for (let i = 0; i < bytes.byteLength; i++) {
+ binary += String.fromCharCode(bytes[i]);
+ }
+ return btoa(binary);
+ } catch (error) {
+ console.error('Error converting ArrayBuffer to Base64:', error);
+ console.error('Buffer:', buffer);
+ console.error('Buffer type:', typeof buffer);
+ console.error('Buffer length:', buffer ? buffer.byteLength : 'N/A');
+ throw error;
}
- return btoa(binary);
}
document.addEventListener('DOMContentLoaded', function() {
if (registrationOptions === null) {
// Step 1: Get registration options
try {
- const response = await fetch('/diary-web/public/register.php', {
+ const response = await fetch('register.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
async function startWebAuthnRegistration() {
try {
+ // Vérifier si l'API WebAuthn est prise en charge
+ if (!navigator.credentials || !navigator.credentials.create) {
+ throw new Error('WebAuthn not supported in this browser. Please use a modern browser like Chrome, Firefox, or Edge.');
+ }
+
webauthnMessage.textContent = 'Veuillez toucher votre YubiKey...';
// Convert the registration options to the format expected by the browser
if (credential) {
// Send the attestation response to the server
// Convert credential to a format that can be sent to the server
+ const rawIdBase64 = arrayBufferToBase64(credential.rawId);
+ const attestationObjectBase64 = arrayBufferToBase64(credential.response.attestationObject);
+ const clientDataJSONBase64 = arrayBufferToBase64(credential.response.clientDataJSON);
+
+ console.log('Raw ID (Base64):', rawIdBase64);
+ console.log('Attestation Object (Base64):', attestationObjectBase64);
+ console.log('Client Data JSON (Base64):', clientDataJSONBase64);
+
+ // Vérifier que les données Base64 sont valides
+ if (!rawIdBase64 || !attestationObjectBase64 || !clientDataJSONBase64) {
+ throw new Error('Données Base64 invalides');
+ }
+
const attestationResponse = {
id: credential.id,
- rawId: arrayBufferToBase64(credential.rawId),
+ rawId: rawIdBase64,
response: {
- attestationObject: arrayBufferToBase64(credential.response.attestationObject),
- clientDataJSON: arrayBufferToBase64(credential.response.clientDataJSON)
+ attestationObject: attestationObjectBase64,
+ clientDataJSON: clientDataJSONBase64
},
type: credential.type
};
- const response = await fetch('/diary-web/public/register.php', {
+ console.log('Attestation response:', attestationResponse);
+
+ try {
+ const attestationResponseJSON = JSON.stringify(attestationResponse);
+ console.log('Attestation response JSON:', attestationResponseJSON);
+
+ const response = await fetch('register.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
- body: `attestationResponse=${encodeURIComponent(JSON.stringify(attestationResponse))}`
+ body: `attestationResponse=${encodeURIComponent(attestationResponseJSON)}`
});
const responseText = await response.text();
webauthnMessage.textContent = 'Erreur: Réponse du serveur invalide. Voir console pour détails.';
registerButton.disabled = false;
}
+ } catch (error) {
+ console.error('Fetch error:', error);
+ console.error('Fetch error details:', error.message, error.stack);
+ webauthnMessage.textContent = 'Erreur lors de l\'envoi des données: ' + error.message;
+ registerButton.disabled = false;
+ }
} else {
webauthnMessage.textContent = 'Aucune credential reçue';
registerButton.disabled = false;