AuthResetPassword - Mot de passe oublié

Spécification design de l’écran login-reset-password.ftl Keycloak. HTML+CSS pur.

Contexte d’usage

Affiché quand l’usager clique sur “Mot de passe oublié ?” depuis la mire de connexion. L’écran demande l’identifiant (généralement email) pour envoyer un lien de réinitialisation.

Rendu visuel

Mot de passe oublié

Saisissez votre adresse email. Vous recevrez un lien pour définir un nouveau mot de passe.

Retour à la connexion

Code HTML pour login-reset-password.ftl

<div class="pf-auth-page">
  <div class="ori-card ori-card--elevated pf-auth-card">
    <div class="ori-card__body pf-auth-body">
      <div class="pf-auth-brand">
        <span class="ori-logo">
          <img src="${url.resourcesPath}/img/logo-pf.svg" alt="" class="ori-logo__crest" />
          <span class="ori-logo__text">
            <span class="ori-logo__title">Polynésie française</span>
            <span class="ori-logo__subtitle">${realm.displayName!''}</span>
          </span>
        </span>
      </div>

      <div class="pf-auth-intro">
        <h1 class="pf-auth-title">${msg("emailForgotTitle")}</h1>
        <p class="pf-auth-description">${msg("emailInstruction")}</p>
      </div>

      <#if message?has_content>
        <div class="ori-alert ori-alert--<#if message.type=='success'>success<#elseif message.type=='warning'>warning<#else>danger</#if>" role="alert">
          <div class="ori-alert__content">${kcSanitize(message.summary)?no_esc}</div>
        </div>
      </#if>

      <form id="kc-reset-password-form" action="${url.loginAction}" method="post" class="pf-auth-form">
        <div class="ori-field">
          <label for="username" class="ori-field__label ori-field__label--required">
            <#if !realm.loginWithEmailAllowed>${msg("username")}
            <#elseif !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}
            <#else>${msg("email")}</#if>
          </label>
          <input id="username" name="username"
                 type="<#if realm.registrationEmailAsUsername>email<#else>text</#if>"
                 autocomplete="<#if realm.registrationEmailAsUsername>email<#else>username</#if>"
                 value="${(auth.attemptedUsername!'')}" required class="ori-input"
                 aria-invalid="<#if messagesPerField.existsError('username')>true</#if>" />
        </div>
        <button type="submit" class="ori-btn ori-btn--primary ori-btn--block">${msg("doSubmit")}</button>
      </form>

      <p class="pf-auth-back">
        <a href="${url.loginUrl}" class="ori-link">${msg("backToLogin")}</a>
      </p>
    </div>
  </div>
</div>

CSS d’accompagnement

.pf-auth-intro { display: flex; flex-direction: column; gap: 0.5rem; text-align: center; }
.pf-auth-description { margin: 0; font-size: 0.875rem; color: var(--color-text-secondary); }
.pf-auth-back { margin: 0; text-align: center; font-size: 0.875rem; }

Spécification fonctionnelle

Libellés

emailForgotTitle=Mot de passe oublié
emailInstruction=Saisissez votre adresse email. Vous recevrez un lien pour définir un nouveau mot de passe.
email=Adresse email
username=Identifiant
usernameOrEmail=Identifiant ou email
doSubmit=Envoyer le lien
backToLogin=Retour à la connexion

Variantes selon la config du realm

ConfigEffet
realm.loginWithEmailAllowed = falseLibellé “Identifiant” + type="text"
realm.registrationEmailAsUsername = trueLibellé “Adresse email” + type="email"
DéfautLibellé “Identifiant ou email” + type="text"

États de message Keycloak

L’écran peut afficher un message de succès, warning ou erreur selon le message.type :

  • success : “Si l’adresse existe, un email a été envoyé.” (confirmation - pas de fuite d’information sur l’existence du compte)
  • warning : “Trop de tentatives, réessayez dans X minutes.” (rate limit)
  • error : Erreur technique

Le composant <div class="ori-alert ori-alert--<type>"> adapte sa couleur à message.type.

Sécurité

  • Ne jamais confirmer ou infirmer l’existence d’un compte dans le message de retour. Toujours répondre “Si l’adresse existe, un email a été envoyé.” quel que soit le résultat (Keycloak gère ça par défaut).
  • Rate limiting côté Keycloak (à configurer côté realm) pour éviter l’énumération.