Aller au contenu

Formulaire de connexion

Pattern — Formulaire de connexion

Le formulaire de connexion est l’une des pages les plus critiques d’un service numérique. Il doit être simple, rassurant et sans obstacles.


Structure

<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Connexion — Nom du service</title>
<link rel="stylesheet" href="/styles/tds.css">
</head>
<body>
<!-- Skip link -->
<a href="#main-content" class="tds-skip-link">Aller au contenu principal</a>
<!-- En-tête gouvernemental -->
<header class="tds-gov-header" role="banner">
<div class="tds-gov-header__brand">
<img src="/images/armoiries-tchad.svg" alt="République du Tchad" height="48">
<span>Nom du ministère ou service</span>
</div>
</header>
<!-- Contenu principal -->
<main id="main-content">
<div style="
max-width: 480px;
margin: var(--tds-spacing-16) auto;
padding: 0 var(--tds-spacing-4);
">
<!-- Résumé d'erreurs (visible uniquement si erreurs) -->
<div
class="tds-alert tds-alert--danger"
role="alert"
aria-labelledby="error-summary-heading"
hidden
>
<h2 id="error-summary-heading" style="
font-size: var(--tds-font-size-lg);
font-weight: var(--tds-font-weight-semibold);
margin-bottom: var(--tds-spacing-3);
">
Il y a des erreurs dans votre saisie
</h2>
<ul id="error-summary-list">
<!-- Liste des erreurs injectée dynamiquement -->
</ul>
</div>
<h1 style="
font-size: var(--tds-font-size-4xl);
font-weight: var(--tds-font-weight-semibold);
margin-bottom: var(--tds-spacing-8);
">
Connexion
</h1>
<form method="post" action="/auth/login" novalidate>
<!-- Token CSRF -->
<input type="hidden" name="_token" value="{{csrf_token}}">
<!-- Champ e-mail -->
<div class="tds-field" style="margin-bottom: var(--tds-spacing-5);">
<label class="tds-field__label" for="email">
Adresse e-mail
</label>
<input
id="email"
name="email"
type="email"
class="tds-input tds-input--md"
autocomplete="email"
spellcheck="false"
required
aria-required="true"
value="{{old_email}}"
>
<!-- Affiché si erreur -->
<p id="email-error" class="tds-error-text" role="alert" hidden>
<!-- Message d'erreur -->
</p>
</div>
<!-- Champ mot de passe -->
<div class="tds-field" style="margin-bottom: var(--tds-spacing-6);">
<label class="tds-field__label" for="password">
Mot de passe
</label>
<input
id="password"
name="password"
type="password"
class="tds-input tds-input--md"
autocomplete="current-password"
required
aria-required="true"
>
<p id="password-error" class="tds-error-text" role="alert" hidden>
<!-- Message d'erreur -->
</p>
</div>
<!-- Actions -->
<div style="
display: flex;
flex-direction: column;
gap: var(--tds-spacing-3);
">
<button type="submit" class="tds-button tds-button--primary tds-button--md">
Se connecter
</button>
<a
href="/auth/forgot-password"
style="
font-size: var(--tds-font-size-sm);
color: var(--tds-color-blue-500);
text-decoration: underline;
text-align: center;
"
>
Mot de passe oublié ?
</a>
</div>
</form>
</div>
</main>
</body>
</html>

Gestion des erreurs

Erreur d’identifiants

<!-- ✅ Message générique (sécurisé) -->
<div class="tds-alert tds-alert--danger" role="alert">
<strong>Identifiants incorrects.</strong>
Vérifiez votre adresse e-mail et votre mot de passe, puis réessayez.
</div>
<!-- ❌ Message spécifique (à éviter) -->
<div class="tds-alert tds-alert--danger" role="alert">
Ce compte n'existe pas. <!-- Révèle l'existence du compte -->
</div>

Erreur de validation de champ

<div class="tds-field">
<label class="tds-field__label" for="email">Adresse e-mail</label>
<input
id="email"
type="email"
class="tds-input tds-input--md tds-input--error"
aria-invalid="true"
aria-describedby="email-error"
value="adresse-invalide"
>
<p id="email-error" class="tds-error-text" role="alert">
Saisissez une adresse e-mail valide. Exemple : nom@domaine.td
</p>
</div>

Points de vigilance

  • Pas d’autocomplete=“off” — laisser le gestionnaire de mots de passe fonctionner
  • Pas de blocage du copier-coller — facilite l’usage des gestionnaires de mots de passe
  • Limiter les tentatives — implémenter un rate limiting côté serveur
  • HTTPS obligatoire — le formulaire de connexion doit toujours être sur HTTPS
  • Bouton “Afficher le mot de passe” — optionnel mais recommandé pour l’accessibilité