false, 'error' => 'Méthode non autorisée']); exit; } $data = json_decode(file_get_contents('php://input'), true); $identifiant = isset($data['identifiant']) ? trim((string) $data['identifiant']) : ''; $motdepasse = isset($data['motdepasse']) ? (string) $data['motdepasse'] : ''; if ($identifiant === '' || $motdepasse === '') { http_response_code(400); echo json_encode(['success' => false, 'error' => 'Identifiant et mot de passe sont obligatoires.']); exit; } try { $pdoRouter = getRouterConnection(); } catch (PDOException $e) { http_response_code(500); echo json_encode(['success' => false, 'error' => 'Connexion à MIRADOR impossible']); exit; } // Comparaison directe sur l'email : la collation utf8mb4_0900_ai_ci déjà en // place sur MIRADOR (comme sur les autres bases ASPIC) est nativement // insensible à la casse et aux accents, pas besoin d'UPPER() ici. $stmt = $pdoRouter->prepare( 'SELECT MIR_Code, MIR_MDPHash, MIR_ServeurHost, MIR_ServeurPort, MIR_BaseNom FROM MIR_Users WHERE MIR_Email = ? AND MIR_Actif = 1' ); $stmt->execute([$identifiant]); $routage = $stmt->fetch(); // Hash factice comparé même quand l'email est inconnu (password_verify() // tourne alors quand même) : évite qu'une différence de temps de réponse // laisse deviner qu'une adresse n'existe pas dans MIRADOR. Valeur sans // signification, générée une fois pour toutes, jamais utilisée comme vrai // mot de passe. const HASH_FACTICE = '$2y$12$wni9cLq0BKttPzU0xAPM9uX/HMzu9UJhlOMj32H6/wLmkjlNfZ1cm'; $hashAVerifier = $routage['MIR_MDPHash'] ?? HASH_FACTICE; if (!$routage || !password_verify($motdepasse, $hashAVerifier)) { // Message volontairement générique : ne pas révéler si c'est l'identifiant // ou le mot de passe qui est en cause. Le compteur d'essais / la sortie au // 3e échec sont gérés côté front, pas ici (voir en-tête de ce fichier). echo json_encode(['success' => false]); exit; } // Coordonnées de la base de travail propre à cet utilisateur : posées en // session pour que getDbConnection() (db.php) route tous les prochains // appels de CETTE session vers la bonne base, sans qu'il faille les // repasser en paramètre à chaque endpoint. $_SESSION['USR_Code'] = $routage['MIR_Code']; $_SESSION['ASPIC_DB_HOST'] = $routage['MIR_ServeurHost']; $_SESSION['ASPIC_DB_PORT'] = (int) $routage['MIR_ServeurPort']; $_SESSION['ASPIC_DB_NAME'] = $routage['MIR_BaseNom']; // Nom affiché : toujours porté par ASP_Users de la base cible (MIRADOR ne // connaît que l'email/code/mot de passe/routage, pas le nom complet). Un // échec de connexion à cette base cible est remonté explicitement — plutôt // que de laisser entrer un utilisateur dans une base injoignable, ce qui // ferait échouer silencieusement tous les écrans suivants. try { $pdoCible = getDbConnection(); } catch (PDOException $e) { session_unset(); http_response_code(500); echo json_encode(['success' => false, 'error' => 'Connexion à la base de travail impossible']); exit; } $stmtNom = $pdoCible->prepare('SELECT USR_Nom FROM ASP_Users WHERE USR_Code = ?'); $stmtNom->execute([$routage['MIR_Code']]); $nom = $stmtNom->fetchColumn(); echo json_encode([ 'success' => true, 'user' => [ 'USR_Code' => $routage['MIR_Code'], 'USR_Nom' => $nom !== false ? $nom : null, ], ]);