feat(auth): premier login via AppAuth — remédiation automatique des anciens comptes
- MembreKeycloakSyncService: completerPremierLogin retourne un enum PremierLoginResultat (COMPLETE / REAUTH_REQUIS / NON_APPLICABLE) au lieu d'un boolean - Détection automatique des anciens comptes (sans UPDATE_PASSWORD ni marqueur KC): assigne UPDATE_PASSWORD + attribut premiere_password_pending dans Keycloak et retourne REAUTH_REQUIS pour que Flutter re-déclenche AppAuth - Détection du mot de passe changé: marqueur présent + UPDATE_PASSWORD absent → COMPLETE - createUserDTOFromMembre: ajoute l'attribut premiere_password_pending=true à la création - CompteAdherentResource.getMonStatut: retourne reAuthRequired=true quand REAUTH_REQUIS
This commit is contained in:
@@ -114,8 +114,32 @@ public class CompteAdherentResource {
|
||||
.filter(s -> s != null && !s.isBlank())
|
||||
.orElse("ACTIF");
|
||||
|
||||
// Auto-activer si le membre a été créé par un admin dont l'org a une souscription active.
|
||||
// Couvre les membres créés avant l'auto-activation à la création ET les cas limites futurs.
|
||||
// Premier login : Keycloak a déjà forcé UPDATE_PASSWORD dans le Chrome Custom Tab.
|
||||
// Si l'utilisateur possède un token valide (@Authenticated), c'est la preuve que
|
||||
// le changement de mot de passe est complété — mettre à jour la DB et assigner les rôles.
|
||||
// Pour les anciens comptes (sans UPDATE_PASSWORD assigné), le service assigne automatiquement
|
||||
// la required action et retourne REAUTH_REQUIS pour que Flutter déclenche une nouvelle auth.
|
||||
boolean premierLoginComplet = false;
|
||||
boolean reAuthRequired = false;
|
||||
if (membreOpt.isPresent() && Boolean.TRUE.equals(membreOpt.get().getPremiereConnexion())) {
|
||||
Membre m = membreOpt.get();
|
||||
MembreKeycloakSyncService.PremierLoginResultat resultat =
|
||||
membreKeycloakSyncService.completerPremierLogin(m.getId());
|
||||
if (resultat == MembreKeycloakSyncService.PremierLoginResultat.COMPLETE) {
|
||||
premierLoginComplet = true;
|
||||
// Relire le statutCompte après activation éventuelle
|
||||
statutCompte = membreRepository.findByIdOptional(m.getId())
|
||||
.map(Membre::getStatutCompte)
|
||||
.orElse(statutCompte);
|
||||
LOG.infof("Premier login complété au statut pour %s → %s", m.getEmail(), statutCompte);
|
||||
} else if (resultat == MembreKeycloakSyncService.PremierLoginResultat.REAUTH_REQUIS) {
|
||||
reAuthRequired = true;
|
||||
LOG.infof("Réauthentification requise pour %s (UPDATE_PASSWORD assigné)", m.getEmail());
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback : auto-activer si EN_ATTENTE_VALIDATION et org a souscription active
|
||||
// (membres sans premiereConnexion=true ou créés avant cette logique)
|
||||
if ("EN_ATTENTE_VALIDATION".equals(statutCompte) && membreOpt.isPresent()) {
|
||||
Membre m = membreOpt.get();
|
||||
UUID orgId = membreOrganisationRepo.findFirstByMembreId(m.getId())
|
||||
@@ -136,12 +160,13 @@ public class CompteAdherentResource {
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("statutCompte", statutCompte);
|
||||
|
||||
// Signaler si le membre doit changer son mot de passe (premier login)
|
||||
boolean changerMotDePasseRequis = membreOpt
|
||||
.map(m -> Boolean.TRUE.equals(m.getPremiereConnexion()))
|
||||
.orElse(false);
|
||||
response.put("changerMotDePasseRequis", changerMotDePasseRequis);
|
||||
// changerMotDePasseRequis = false : Keycloak gère nativement le changement de mot de passe
|
||||
// via la required action UPDATE_PASSWORD dans le Chrome Custom Tab (AppAuth).
|
||||
response.put("changerMotDePasseRequis", false);
|
||||
// Indique à Flutter que le token doit être rafraîchi (nouveaux rôles MEMBRE/MEMBRE_ACTIF)
|
||||
response.put("premierLoginComplet", premierLoginComplet);
|
||||
// Indique à Flutter qu'une réauthentification est nécessaire (UPDATE_PASSWORD vient d'être assigné)
|
||||
response.put("reAuthRequired", reAuthRequired);
|
||||
|
||||
// Enrichir avec l'état d'onboarding pour les comptes en attente
|
||||
if ("EN_ATTENTE_VALIDATION".equals(statutCompte)) {
|
||||
|
||||
Reference in New Issue
Block a user