# Requirements Document ## Introduction Cette fonctionnalité ajoute une couche d'authentification à l'application mono-utilisateur SchotzIAD KM Tracker. Elle introduit un compte unique (adresse email + mot de passe haché), une session par jeton JWT, la protection de toutes les routes de données existantes, un mécanisme de réinitialisation de mot de passe par email (avec repli de journalisation en l'absence de configuration SMTP), et réorganise l'onboarding en deux étapes : d'abord l'inscription et la connexion, puis la saisie du profil et du premier véhicule (comportement actuel inchangé). L'application étant mono-utilisateur, la création de compte n'est autorisée qu'une seule fois : lorsqu'aucun compte n'existe encore. Une fois le compte créé, seule la connexion reste possible. ## Glossary - **Systeme** : L'application SchotzIAD KM Tracker dans son ensemble (frontend Angular + backend ASP.NET Core). - **Service_Auth** : Le composant backend responsable de l'inscription, de la connexion, de la déconnexion et de la réinitialisation de mot de passe. - **API** : L'ensemble des points d'accès HTTP exposés par le backend ASP.NET Core. - **Compte** : L'unique enregistrement utilisateur contenant l'adresse email (identifiant) et le mot de passe haché. - **Email** : L'adresse électronique servant d'identifiant de connexion au Compte. - **Mot_De_Passe** : Le secret d'authentification saisi par l'utilisateur, d'une longueur minimale de 8 caractères. - **Jeton_JWT** : Le jeton JSON Web Token émis par le Service_Auth à la connexion, transmis par le navigateur pour authentifier les appels aux routes protégées. - **Jeton_Reset** : Le jeton à usage unique et à durée de vie limitée émis lors d'une demande de réinitialisation de mot de passe. - **Route_Protegee** : Toute route ou point d'API accessible uniquement à un utilisateur authentifié (trajets, profil, véhicules, carnet d'adresses, barème, résumés, montants, exports PDF, recalcul de distances). - **Route_Publique** : Toute route ou point d'API accessible sans authentification (inscription lorsqu'aucun Compte n'existe, connexion, demande de réinitialisation, réinitialisation via Jeton_Reset). - **Onboarding** : Le parcours de première utilisation, désormais organisé en deux étapes. - **Etape_1_Onboarding** : La première étape de l'Onboarding : inscription (Email + Mot_De_Passe) puis redirection vers la page de connexion. - **Etape_2_Onboarding** : La seconde étape de l'Onboarding, accessible uniquement après connexion : saisie du profil (nom, prénom, matricule, adresse de domicile) et du premier véhicule. - **Garde_Profil** : La garde de route existante `profilConfigureGuard` qui vérifie l'état de configuration du profil via `GET /api/profil/etat`. - **Garde_Auth** : La garde de route frontend qui empêche l'accès aux pages protégées tant que l'utilisateur n'est pas authentifié. - **Service_SMTP** : Le serveur d'envoi de courriels configuré par variables d'environnement (hôte, port, identifiants, expéditeur). - **Duree_Validite_Jeton** : La durée de vie configurée du Jeton_JWT, valant 12 heures (720 minutes) par défaut et configurable par variable d'environnement (par exemple `Jwt:ExpirationMinutes` / `JWT__ExpirationMinutes`). - **Duree_Validite_Reset** : La durée de vie configurée du Jeton_Reset (durée limitée après laquelle le jeton expire), valant 1 heure (60 minutes) par défaut et configurable par variable d'environnement (par exemple `Auth:ResetTokenLifetimeMinutes`). ## Requirements ### Requirement 1 : Inscription du compte unique **User Story:** En tant qu'utilisateur de première utilisation, je veux créer un compte avec mon adresse email et un mot de passe, afin de sécuriser l'accès à mon suivi kilométrique. #### Acceptance Criteria 1. WHEN une inscription est demandée ET qu'aucun Compte n'existe, THE Service_Auth SHALL créer le Compte avec l'Email fourni et le Mot_De_Passe fourni. 2. IF une inscription est demandée ALORS qu'un Compte existe déjà, THEN THE Service_Auth SHALL rejeter la demande avec un code d'erreur HTTP 409 et un message indiquant qu'un compte existe déjà. 3. IF le Mot_De_Passe fourni comporte moins de 8 caractères, THEN THE Service_Auth SHALL rejeter la demande avec un code d'erreur HTTP 400 et un message indiquant la longueur minimale requise. 4. IF l'Email fourni n'est pas une adresse électronique valide sur le plan syntaxique, THEN THE Service_Auth SHALL rejeter la demande avec un code d'erreur HTTP 400. 5. WHEN le Service_Auth crée le Compte, THE Service_Auth SHALL stocker le Mot_De_Passe sous forme hachée. 6. WHEN le Compte est créé avec succès, THE Systeme SHALL rediriger l'utilisateur vers la page de connexion. ### Requirement 2 : Connexion **User Story:** En tant qu'utilisateur disposant d'un compte, je veux me connecter avec mon email et mon mot de passe, afin d'accéder à mes données. #### Acceptance Criteria 1. WHEN une connexion est demandée avec un Email et un Mot_De_Passe correspondant au Compte, THE Service_Auth SHALL émettre un Jeton_JWT et le retourner à l'utilisateur. 2. IF une connexion est demandée avec un Email inconnu ou un Mot_De_Passe incorrect, THEN THE Service_Auth SHALL rejeter la demande avec un code d'erreur HTTP 401 et un message générique d'identifiants invalides. 3. WHEN un Jeton_JWT est émis, THE Systeme SHALL stocker le Jeton_JWT côté navigateur. 4. WHEN un Jeton_JWT est émis, THE Service_Auth SHALL associer au Jeton_JWT une date d'expiration. ### Requirement 3 : Déconnexion **User Story:** En tant qu'utilisateur connecté, je veux me déconnecter, afin que ma session ne reste pas active sur l'appareil. #### Acceptance Criteria 1. WHEN l'utilisateur demande la déconnexion, THE Systeme SHALL supprimer le Jeton_JWT stocké côté navigateur. 2. WHEN le Jeton_JWT a été supprimé, THE Systeme SHALL rediriger l'utilisateur vers la page de connexion. ### Requirement 4 : Protection des routes et de l'API **User Story:** En tant que propriétaire des données, je veux que toutes mes données soient inaccessibles sans authentification, afin de préserver leur confidentialité. #### Acceptance Criteria 1. WHEN un appel est adressé à une Route_Protegee avec un Jeton_JWT valide et non expiré, THE API SHALL traiter la requête normalement. 2. IF un appel est adressé à une Route_Protegee sans Jeton_JWT ou avec un Jeton_JWT invalide, THEN THE API SHALL rejeter la requête avec un code d'erreur HTTP 401. 3. IF un appel est adressé à une Route_Protegee avec un Jeton_JWT expiré, THEN THE API SHALL rejeter la requête avec un code d'erreur HTTP 401. 4. THE API SHALL classer comme Route_Protegee les points d'accès de trajets, profil, véhicules, carnet d'adresses, barème, résumés, montants réglés, exports PDF et recalcul de distances. 5. THE API SHALL classer comme Route_Publique les points d'accès d'inscription, de connexion, de demande de réinitialisation et de réinitialisation via Jeton_Reset. 6. WHEN un utilisateur non authentifié tente d'accéder à une page frontend protégée, THE Garde_Auth SHALL rediriger l'utilisateur vers la page de connexion. 7. WHEN l'API rejette un appel frontend avec un code HTTP 401, THE Systeme SHALL supprimer le Jeton_JWT stocké et rediriger l'utilisateur vers la page de connexion. ### Requirement 5 : Expiration et validité du jeton **User Story:** En tant que propriétaire des données, je veux que ma session expire après une durée définie, afin de limiter la fenêtre d'accès en cas de compromission de l'appareil. #### Acceptance Criteria 1. WHILE le Jeton_JWT n'a pas atteint sa date d'expiration, THE API SHALL considérer le Jeton_JWT comme valide. 2. WHEN le Jeton_JWT atteint sa date d'expiration, THE API SHALL considérer le Jeton_JWT comme invalide. 3. IF un Jeton_JWT présente une signature non valide, THEN THE API SHALL considérer le Jeton_JWT comme invalide. 4. WHEN un Jeton_JWT est émis, THE Service_Auth SHALL fixer sa date d'expiration à 12 heures après l'émission par défaut. 5. THE Systeme SHALL permettre de configurer la Duree_Validite_Jeton via une variable d'environnement (par exemple `JWT__ExpirationMinutes`), avec une valeur par défaut de 720 minutes. ### Requirement 6 : Demande de réinitialisation de mot de passe **User Story:** En tant qu'utilisateur ayant oublié mon mot de passe, je veux demander un lien de réinitialisation par email, afin de retrouver l'accès à mon compte. #### Acceptance Criteria 1. WHEN une demande de réinitialisation est reçue pour un Email correspondant au Compte, THE Service_Auth SHALL générer un Jeton_Reset à usage unique assorti d'une Duree_Validite_Reset. 2. WHEN un Jeton_Reset est généré, THE Service_Auth SHALL fixer l'expiration du Jeton_Reset à 1 heure après sa génération par défaut. 3. THE Systeme SHALL permettre de configurer la Duree_Validite_Reset via une variable d'environnement (par exemple `Auth__ResetTokenLifetimeMinutes`), avec une valeur par défaut de 60 minutes. 4. WHEN un Jeton_Reset est généré ET que le Service_SMTP est configuré, THE Service_Auth SHALL envoyer par email un lien de réinitialisation contenant le Jeton_Reset. 5. IF aucun Service_SMTP n'est configuré, THEN THE Service_Auth SHALL journaliser côté serveur le lien de réinitialisation contenant le Jeton_Reset. 6. WHEN une demande de réinitialisation est reçue pour un Email inconnu, THE Service_Auth SHALL retourner la même réponse de succès générique que pour un Email connu, sans indiquer si l'Email correspond à un Compte. 7. THE Service_SMTP SHALL être configuré par les variables d'environnement d'hôte, de port, d'identifiants et d'expéditeur. ### Requirement 7 : Réinitialisation du mot de passe via jeton **User Story:** En tant qu'utilisateur ayant reçu un lien de réinitialisation, je veux définir un nouveau mot de passe via ce lien, afin de restaurer l'accès à mon compte. #### Acceptance Criteria 1. WHEN une réinitialisation est soumise avec un Jeton_Reset valide, non expiré et non utilisé, ET un nouveau Mot_De_Passe d'au moins 8 caractères, THE Service_Auth SHALL remplacer le Mot_De_Passe du Compte par la version hachée du nouveau Mot_De_Passe. 2. WHEN un Jeton_Reset est utilisé avec succès, THE Service_Auth SHALL invalider le Jeton_Reset pour tout usage ultérieur. 3. IF une réinitialisation est soumise avec un Jeton_Reset expiré, THEN THE Service_Auth SHALL rejeter la demande avec un code d'erreur HTTP 400 et un message indiquant que le lien a expiré. 4. IF une réinitialisation est soumise avec un Jeton_Reset inconnu ou déjà utilisé, THEN THE Service_Auth SHALL rejeter la demande avec un code d'erreur HTTP 400 et un message indiquant que le lien est invalide. 5. IF une réinitialisation est soumise avec un nouveau Mot_De_Passe de moins de 8 caractères, THEN THE Service_Auth SHALL rejeter la demande avec un code d'erreur HTTP 400 et un message indiquant la longueur minimale requise. 6. WHEN la réinitialisation aboutit, THE Systeme SHALL rediriger l'utilisateur vers la page de connexion. ### Requirement 8 : Sécurité des mots de passe **User Story:** En tant que propriétaire des données, je veux que mon mot de passe ne soit jamais stocké ou exposé en clair, afin de me protéger en cas de fuite de données. #### Acceptance Criteria 1. THE Service_Auth SHALL stocker le Mot_De_Passe uniquement sous forme hachée avec un algorithme de hachage de mot de passe à sel. 2. THE Service_Auth SHALL exclure le Mot_De_Passe haché de toute réponse d'API. 3. WHEN le Service_Auth vérifie un Mot_De_Passe lors de la connexion, THE Service_Auth SHALL comparer la valeur saisie à la version hachée stockée sans reconstituer le Mot_De_Passe en clair. ### Requirement 9 : Onboarding en deux étapes **User Story:** En tant qu'utilisateur de première utilisation, je veux créer mon compte puis me connecter avant de renseigner mon profil, afin que mes données de profil soient protégées dès le départ. #### Acceptance Criteria 1. WHEN l'utilisateur démarre l'Onboarding ET qu'aucun Compte n'existe, THE Systeme SHALL présenter l'Etape_1_Onboarding d'inscription. 2. WHEN l'Etape_1_Onboarding d'inscription aboutit, THE Systeme SHALL rediriger l'utilisateur vers la page de connexion. 3. WHILE l'utilisateur n'est pas authentifié, THE Systeme SHALL empêcher l'accès à l'Etape_2_Onboarding. 4. WHEN l'utilisateur est authentifié ET que le profil n'est pas encore configuré, THE Garde_Profil SHALL autoriser l'accès à l'Etape_2_Onboarding de saisie du profil et du premier véhicule. 5. THE Etape_2_Onboarding SHALL conserver le comportement actuel de saisie du profil (nom, prénom, matricule, adresse de domicile) et du premier véhicule. 6. WHEN l'utilisateur authentifié a configuré son profil, THE Garde_Profil SHALL autoriser l'accès aux Routes_Protegees applicatives.