# Spécifications Techniques et Fonctionnelles – Module d'Authentification

*   **Version :** 1.0
*   **Date :** 31 octobre 2025
*   **Auteur :** Yoann

---

### 1. Introduction et Objectifs

Ce document décrit en détail le fonctionnement, la logique et les exigences de sécurité du module d'authentification du projet. Il a pour but de servir de guide pour le développement, la maintenance et les futures évolutions.

Le périmètre inclut : la création de compte, la connexion, la gestion des mots de passe, et l'authentification à deux facteurs (2FA).

---

### 2. Environnement Technique

*   **Langage Backend :** PHP (version 8.1 ou supérieure recommandée).
*   **Base de Données :** MySQL ou MariaDB, administrée via phpMyAdmin.
*   **Langages Frontend :** HTML5, CSS3, JavaScript (ES6+). L'éventualité d'une migration vers un framework comme React.js est à considérer pour des évolutions futures.

---

### 3. Structure de la Base de Données (Schéma SQL) - **Obsolète - voir la version dans ArchitectureTechnique.md**

Les tables suivantes sont nécessaires pour supporter les fonctionnalités d'authentification.

#### Table `users`
Stocke les informations principales des utilisateurs.

```sql
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    is_active BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
```


#### Table `email_verifications`
Gère les tokens pour la validation des adresses email à l'inscription.

```sql
CREATE TABLE email_verifications (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    token VARCHAR(255) NOT NULL UNIQUE,
    expires_at TIMESTAMP NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
```


#### Table `password_resets`
Gère les tokens pour la réinitialisation des mots de passe.

```sql
CREATE TABLE password_resets (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(100) NOT NULL,
    token VARCHAR(255) NOT NULL UNIQUE,
    expires_at TIMESTAMP NOT NULL,
    FOREIGN KEY (email) REFERENCES users(email) ON DELETE CASCADE
);
```


#### Table `users_2fa`
Stocke les informations relatives à l'authentification à deux facteurs pour chaque utilisateur.

```sql
CREATE TABLE users_2fa (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL UNIQUE,
    secret_key_encrypted VARCHAR(255) NOT NULL, -- Le secret doit être chiffré
    is_enabled BOOLEAN DEFAULT TRUE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
```


#### Table `users_2fa_backup_codes`
Stocke les codes de secours à usage unique pour le 2FA.

```sql
CREATE TABLE users_2fa_backup_codes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    code_hash VARCHAR(255) NOT NULL, -- Les codes doivent être hachés
    used_at TIMESTAMP NULL,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
```


---

### 4. Spécifications Fonctionnelles (Parcours Utilisateurs)

#### 4.1. Inscription
1.  **Formulaire** : L'utilisateur fournit un nom d'utilisateur, une adresse email et un mot de passe.
2.  **Validation (côté serveur)** :
    *   Le nom d'utilisateur et l'email doivent être uniques dans la table `users`.
    *   L'email doit avoir un format valide.
    *   Le mot de passe doit respecter la politique de sécurité (voir section 5.1).
3.  **Création du compte** : Un nouvel enregistrement est créé dans la table `users` avec `is_active = FALSE`.
4.  **Envoi de l'email de confirmation** :
    *   Un token sécurisé et unique est généré et stocké dans `email_verifications` avec une date d'expiration (ex: 24 heures).
    *   Un email est envoyé à l'utilisateur avec un lien contenant ce token.
5.  **Activation du compte** : Lorsque l'utilisateur clique sur le lien, le serveur valide le token, passe `is_active` à `TRUE` dans la table `users` et supprime le token.

#### 4.2. Connexion
1.  **Formulaire** : L'utilisateur saisit son nom d'utilisateur et son mot de passe.
2.  **Vérification des identifiants** : Le système vérifie que le nom d'utilisateur existe, que le compte est actif (`is_active = TRUE`) et que le mot de passe fourni correspond au `password_hash` en utilisant `password_verify()`.
3.  **Étape 2FA** : Si les identifiants sont corrects et que le 2FA est activé pour cet utilisateur, il est redirigé vers une page où il doit saisir le code à 6 chiffres de son application d'authentification.
4.  **Validation du code 2FA** : Le code est validé par rapport au secret de l'utilisateur. Si le code est invalide, l'utilisateur peut aussi utiliser un code de secours.
5.  **Création de la session** : Si tout est correct, la session est créée et l'utilisateur est redirigé vers son espace personnel.

#### 4.3. Déconnexion
1.  L'utilisateur clique sur le bouton "Se déconnecter".
2.  Le serveur exécute `session_destroy()` pour supprimer toutes les données de session.
3.  Le cookie de session est invalidé côté client. L'utilisateur est redirigé vers la page de connexion.

#### 4.4. Mot de Passe Oublié
1.  **Formulaire** : L'utilisateur saisit l'adresse email associée à son compte.
2.  **Génération du token** : Si l'email existe, un token sécurisé et unique est généré et stocké dans `password_resets` avec une date d'expiration (ex: 1 heure).
3.  **Envoi de l'email** : Un email contenant un lien de réinitialisation avec le token est envoyé.
4.  **Formulaire de réinitialisation** : En cliquant sur le lien, l'utilisateur accède à une page où il peut définir un nouveau mot de passe.
5.  **Mise à jour** : Le serveur valide le token, met à jour le `password_hash` de l'utilisateur avec le nouveau mot de passe et supprime le token.

#### 4.5. Modification du Mot de Passe (Utilisateur connecté)
1.  **Formulaire** : Dans son profil, l'utilisateur saisit son mot de passe actuel, le nouveau mot de passe et une confirmation du nouveau mot de passe.
2.  **Validation** : Le système vérifie que le mot de passe actuel est correct en utilisant `password_verify()`. Le nouveau mot de passe doit respecter la politique de sécurité.
3.  **Mise à jour** : Le `password_hash` est mis à jour dans la table `users`.

#### 4.6. Gestion de l'Authentification à Deux Facteurs (2FA)
1.  **Activation initiale** :
    *   Dans son profil, l'utilisateur choisit d'activer le 2FA.
    *   Le système génère un secret partagé unique. Ce secret est stocké de manière **chiffrée** dans la table `users_2fa`.
    *   Un **QR code** est généré à partir du secret et affiché à l'utilisateur pour qu'il le scanne.
    *   Pour confirmer, l'utilisateur doit saisir un code généré par son application.
    *   Une fois confirmé, le système génère une liste de **codes de secours** (ex: 10 codes) qui sont affichés une seule fois à l'utilisateur. Ces codes doivent être stockés **hachés** dans la table `users_2fa_backup_codes`.
2.  **Réinitialisation du 2FA (Utilisateur connecté)** :
    *   Pour modifier ou désactiver le 2FA, l'utilisateur doit d'abord **ressaisir son mot de passe** par mesure de sécurité.
    *   Si le mot de passe est correct, le secret 2FA actuel et les codes de secours sont supprimés de la base de données.
    *   L'utilisateur peut alors choisir de désactiver le 2FA ou de recommencer le processus d'activation pour le lier à un nouvel appareil.

---

### 5. Spécifications Techniques et de Sécurité

#### 5.1. Politique de Mots de Passe
*   **Longueur minimale :** **12 caractères**. La longueur est le facteur de sécurité le plus important.
*   **Complexité :** Aucune exigence de casse, de chiffres ou de symboles. Il est préférable d'éduquer les utilisateurs à utiliser des "phrases de passe".
*   **Vérification contre les fuites :** Le mot de passe soumis sera comparé (de manière sécurisée, via son hash k-anonymisé) à des bases de données de mots de passe compromis (ex: API de Have I Been Pwned).

#### 5.2. Stockage des Mots de Passe
Le stockage se fera en utilisant les fonctions natives de PHP, qui sont la référence en la matière.

```php
// Pour hacher un mot de passe lors de l'inscription
$hash = password_hash($password, PASSWORD_ARGON2ID);

// Pour vérifier un mot de passe lors de la connexion
if (password_verify($password, $hash)) {
    // Le mot de passe est correct
}
```

#### 5.3. Gestion de Session
*   **Sessions natives PHP :** Utiliser `session_start()` au début de chaque script nécessitant une authentification.
*   **Configuration sécurisée :** Configurer les cookies de session via `php.ini` ou `session_set_cookie_params()` avec les attributs suivants :
    *   `HttpOnly` : Empêche l'accès au cookie via JavaScript.
    *   `Secure` : Le cookie n'est envoyé que sur une connexion HTTPS.
    *   `SameSite=Strict` : Protège contre les attaques CSRF.
*   **Régénération d'ID :** Après une connexion réussie ou une élévation de privilèges, l'ID de session doit être régénéré avec `session_regenerate_id(true)` pour prévenir les attaques de fixation de session.
*   **Expiration pour inactivité :** Mettre en place une logique qui enregistre l'heure de la dernière activité dans `$_SESSION`. Si le délai depuis cette heure dépasse une certaine durée (ex: 30 minutes), la session est détruite.

#### 5.4. Implémentation du 2FA
*   **Bibliothèque recommandée :** L'utilisation d'une bibliothèque robuste comme `pragmarx/google2fa-php` est fortement conseillée pour gérer la génération de secrets, de QR codes et la validation des codes TOTP (Time-based One-Time Password).
*   **Stockage du secret :** Le secret partagé de l'utilisateur ne doit JAMAIS être stocké en clair. Il doit être chiffré à l'aide d'une clé de chiffrement stockée en dehors de la base de données (ex: dans un fichier de configuration du serveur), en utilisant les fonctions `openssl_encrypt()` et `openssl_decrypt()` de PHP.

#### 5.5. Protections Diverses
*   **Injection SQL :** Toutes les requêtes SQL doivent utiliser des **requêtes préparées** avec PDO ou MySQLi.
*   **Cross-Site Scripting (XSS) :** Toute donnée provenant de l'utilisateur et affichée dans une page HTML doit être systématiquement échappée avec `htmlspecialchars()`.
*   **Limitation des tentatives (Rate Limiting) :** Mettre en place un mécanisme pour limiter le nombre de tentatives de connexion échouées par adresse IP et/ou par compte sur une période donnée (ex: 5 tentatives par 15 minutes) afin de ralentir les attaques par force brute.
