Les sources d'utilisateurs et la reprise des comptes
Fédération LDAP et Active Directory, User Storage SPI, migration au fil de l'eau, import d'empreintes de mots de passe, identity brokering et doublons : choisir une stratégie par source de vérité.
Sur cette page
Avant de choisir un parcours d’authentification, il faut savoir d’où viennent les comptes. Keycloak peut être lui-même la base des comptes, s’appuyer sur un annuaire existant, lire une base applicative ou déléguer l’authentification à un fournisseur d’identité externe. Chaque option a un coût et des limites, et une même architecture combine souvent plusieurs d’entre elles. Ce cours vous donne de quoi remplir, pour chaque population et chaque application, la colonne « source de vérité ».
Cinq façons d’avoir des utilisateurs dans un realm
| Stratégie | Où vit le compte | Où est vérifié le mot de passe | Native | Cas typique |
|---|---|---|---|---|
| Comptes locaux | base Keycloak | Keycloak | oui | usagers en auto-inscription |
| Fédération LDAP / AD | annuaire (copie locale si import) | annuaire | oui | agents d’un annuaire d’entreprise |
| User Storage SPI | base applicative | selon le provider | extension | base existante qu’on ne peut pas migrer |
| Reprise (import ou migration au fil de l’eau) | base Keycloak après reprise | Keycloak | import natif, migration au fil de l’eau en extension | décommissionnement d’une authentification applicative |
| Identity brokering | fournisseur externe, compte lié en local | fournisseur externe | oui | partenaires, fédération d’identité nationale |
Keycloak cherche toujours un utilisateur d’abord dans sa base locale, puis dans les providers de fédération par ordre de priorité. Si un provider de priorité haute est en panne, la recherche échoue sans basculer sur le suivant. La documentation recommande donc de garder un compte d’administration local, utilisable si l’annuaire est injoignable.
Fédération LDAP et Active Directory
Le provider LDAP se déclare dans User Federation. Trois choix structurent son comportement.
Avec ou sans import. Avec Import Users activé, Keycloak crée une copie locale de chaque utilisateur à sa première apparition (connexion ou recherche). Il peut alors stocker ses propres données : credentials OTP ou WebAuthn, required actions, attributs non mappés. Sans import, l’annuaire est la seule source, et la documentation précise qu’on ne peut plus enregistrer côté Keycloak que les données mappées vers l’annuaire. Les fonctions qui demandent un stockage local peuvent alors ne pas fonctionner : vérifiez en particulier le comportement des facteurs MFA avant de retenir ce mode.
Dans les deux cas, Keycloak n’importe jamais les mots de passe : la vérification se fait toujours par un bind sur l’annuaire.
Le mode d’édition.
| Mode | Modification des attributs mappés | Changement de mot de passe | Usage |
|---|---|---|---|
| READ_ONLY | refusée | refusé | l’annuaire reste maître, Keycloak consomme |
| WRITABLE | écrite dans l’annuaire | écrit dans l’annuaire | Keycloak devient un point de gestion de l’annuaire |
| UNSYNCED | stockée en local seulement | stocké en local | annuaire en lecture seule, mais besoin de modifier côté Keycloak |
Le mode se choisit à la création : les mappers par défaut sont générés selon lui et ne sont pas recalculés si on le change ensuite.
La synchronisation. Les utilisateurs importés se synchronisent à la demande ou par tâche périodique, complète (tous les utilisateurs) ou différentielle (modifiés depuis la dernière synchronisation). La pratique recommandée : une synchronisation complète à la création, puis une synchronisation périodique des changements.
kcadm.sh create "user-storage/$LDAP_ID/sync?action=triggerFullSync" -r academy
kcadm.sh create "user-storage/$LDAP_ID/sync?action=triggerChangedUsersSync" -r academy
Les mappers traduisent l’annuaire vers le modèle Keycloak : attribut utilisateur (mail vers email), nom complet, valeur fixe, group-ldap-mapper (groupes de l’annuaire vers groupes Keycloak), role-ldap-mapper (groupes vers rôles), et pour Active Directory le mapper qui lit userAccountControl (compte désactivé, mot de passe expiré).
Deux nouveautés récentes de la branche 26 concernent Active Directory et les politiques de mots de passe de l’annuaire : les utilisateurs créés dans AD par Keycloak sont activés par défaut (26.1), et une option permet de forcer le changement de mot de passe quand l’annuaire l’exige (26.6). La version déployée détermine donc ce qui est disponible.
User Storage SPI et migration au fil de l’eau
Le User Storage SPI permet d’écrire un provider Java qui présente une base existante (souvent la table des comptes d’une application) comme une source d’utilisateurs. Le provider implémente la recherche d’utilisateurs, la validation des credentials et, s’il le faut, l’écriture. Il peut fonctionner avec ou sans import local, comme le provider LDAP.
La migration au fil de l’eau est un usage particulier de ce SPI :
- l’usager se connecte, Keycloak ne le trouve pas en local ;
- le provider le cherche dans l’ancien système et valide le mot de passe saisi (par lecture de l’empreinte ou par appel d’une API de l’ancien système) ;
- en cas de succès, le provider crée le compte local avec le mot de passe saisi, haché par Keycloak, et coupe le lien avec l’ancien système ;
- les connexions suivantes ne sollicitent plus l’ancien système.
Ce mécanisme évite de connaître le format des empreintes et d’imposer une réinitialisation. Ses contreparties : du code à maintenir, un ancien système qui doit rester joignable pendant toute la période, et des comptes inactifs qui ne migrent jamais. Il faut donc prévoir une date de fin et le sort des comptes restants (import, réinitialisation, suppression).
Importer des comptes avec leurs empreintes
Keycloak 26 lit nativement ces algorithmes : argon2 (défaut hors FIPS depuis la 25), pbkdf2-sha512 (défaut en mode FIPS), pbkdf2-sha256 et pbkdf2 (SHA-1, déprécié). Un compte importé avec une empreinte dans l’un de ces formats peut se connecter immédiatement. À la connexion suivante, si l’algorithme ou le nombre d’itérations diffère de la politique du realm, Keycloak recalcule l’empreinte.
Le credential est décrit par deux chaînes JSON. Exemple pour PBKDF2-SHA256 :
{
"username": "lucie",
"email": "lucie@example.org",
"enabled": true,
"emailVerified": true,
"credentials": [
{
"type": "password",
"secretData": "{\"value\":\"Gq8Z...base64...==\",\"salt\":\"q1w2e3...base64==\",\"additionalParameters\":{}}",
"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
}
]
}
Pour Argon2, credentialData porte en plus les paramètres de l’algorithme dans additionalParameters (type, version, mémoire, parallélisme, longueur). Le plus sûr est de copier la structure d’un credential Argon2 créé par Keycloak lui-même, visible avec kcadm.sh get users/ID/credentials.
L’import se fait par l’API d’import partiel (pour quelques milliers de comptes), par kc.sh import au démarrage pour de gros volumes, ou par la création d’utilisateurs via l’API d’administration.
Tout autre format (bcrypt, scrypt, MD5 ou SHA salé, hachage maison) demande un PasswordHashProvider spécifique. C’est une extension simple, mais elle doit rester déployée tant qu’il reste des empreintes dans ce format.
Identity brokering
Un identity provider déclaré dans le realm délègue l’authentification à un fournisseur externe : OIDC, SAML 2.0, ou réseaux sociaux. Keycloak reste le fournisseur des applications : elles ne voient que les jetons de Keycloak.
À la première connexion via un fournisseur, le flux first broker login s’exécute. Par défaut :
- Review Profile affiche les informations reçues, si elles sont incomplètes ou si le réglage l’impose ;
- Create User If Unique crée le compte local s’il n’existe aucun compte avec le même e-mail ou nom d’utilisateur ;
- sinon, Confirm Link Existing Account propose de lier, puis Verify Existing Account by Email ou by Re-authentication demande la preuve que l’usager possède le compte existant.
Le compte local est ensuite lié au compte externe. L’usager voit ses liaisons dans la console de compte (Comptes liés) et l’administrateur peut en créer par l’API. Les mappers d’IdP importent des claims en attributs, rôles ou groupes, et le sync mode décide si ces données sont mises à jour à chaque connexion (force) ou seulement à la création (import).
D’autres réglages pèsent en architecture : Trust Email (considérer l’e-mail reçu comme vérifié), le flux Post Login (par exemple exiger un facteur supplémentaire après le fournisseur externe), et le paramètre kc_idp_hint qui permet à une application d’envoyer directement l’usager vers un fournisseur.
Doublons et rapprochement de comptes
L’e-mail sert souvent d’identifiant. Trois réglages du realm (onglet Login) l’encadrent :
- Email as username : l’e-mail devient le nom d’utilisateur ;
- Login with email : l’usager peut saisir son e-mail ou son nom d’utilisateur ;
- Duplicate emails : autorise plusieurs comptes avec le même e-mail. Ce réglage est incompatible avec la connexion par e-mail et rend le rapprochement par e-mail du brokering ambigu.
Sources de doublons à anticiper : un agent présent dans l’annuaire et dans une base applicative, un usager qui a créé deux comptes avec deux e-mails, un partenaire qui arrive par un fournisseur externe alors qu’il avait un compte local. Le rapprochement natif se fait sur l’e-mail ou le nom d’utilisateur. Un rapprochement sur une autre clé (matricule, numéro de dossier) demande un authenticator spécifique dans le flux first broker login, ou un traitement en amont de la reprise.
Le tableau des sources de vérité
Pour chaque population, et pour chaque application qui porte ses propres comptes, remplissez une ligne :
| Question | Fédération | Import d’empreintes | Migration au fil de l’eau | Brokering |
|---|---|---|---|---|
| La source reste-t-elle maître ? | oui | non, Keycloak devient maître | non, à terme | oui, pour l’authentification |
| Format d’empreinte à connaître ? | non | oui | non | non |
| Ancien système requis ensuite ? | oui, en permanence | non | oui, pendant la période | oui, en permanence |
| Développement | aucun | aucun si PBKDF2 ou Argon2 | provider Java | aucun en général |
| Réseau | Keycloak doit joindre l’annuaire | aucun | Keycloak doit joindre l’ancien système | navigateur et Keycloak joignent le fournisseur |
Restent les cas non prévus, à recenser explicitement : comptes partagés ou génériques, comptes de service applicatifs, applications qui créent elles-mêmes leurs comptes (via l’API d’administration ou, dans les versions récentes de la branche 26, l’API SCIM), comptes sans e-mail.
Fédérer l'OpenLDAP de test et importer des empreintes
35 min
Installer le lab- Depuis
keycloak-academy-lab/, préparez kcadm et créez le realmacademys’il n’existe pas.
kcadm() { docker compose exec -T keycloak /opt/keycloak/bin/kcadm.sh "$@"; }
kcadm config credentials --server http://localhost:8080 --realm master --user admin --password admin
kcadm create realms -s realm=academy -s enabled=true- Déclarez le provider LDAP en lecture seule avec import. L’URL est celle vue depuis le conteneur Keycloak (service
openldap), paslocalhost.
LDAP_ID=$(kcadm create components -r academy -s name=annuaire-academy -s providerId=ldap \
-s providerType=org.keycloak.storage.UserStorageProvider \
-s 'config.enabled=["true"]' -s 'config.vendor=["other"]' \
-s 'config.connectionUrl=["ldap://openldap:389"]' \
-s 'config.bindDn=["cn=admin,dc=academy,dc=local"]' -s 'config.bindCredential=["admin"]' \
-s 'config.usersDn=["ou=people,dc=academy,dc=local"]' \
-s 'config.usernameLDAPAttribute=["uid"]' -s 'config.rdnLDAPAttribute=["uid"]' \
-s 'config.uuidLDAPAttribute=["entryUUID"]' -s 'config.userObjectClasses=["inetOrgPerson"]' \
-s 'config.editMode=["READ_ONLY"]' -s 'config.importEnabled=["true"]' \
-s 'config.searchScope=["1"]' -s 'config.authType=["simple"]' -i)
kcadm get components -r academy -q parent=$LDAP_ID --fields name,providerId- Ajoutez un mapper de groupes vers
ou=groups(groupesgroupOfNames, appartenance par l’attributmember).
MAPPER_ID=$(kcadm create components -r academy -s name=groupes-ldap -s providerId=group-ldap-mapper \
-s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=$LDAP_ID \
-s 'config."groups.dn"=["ou=groups,dc=academy,dc=local"]' \
-s 'config."group.name.ldap.attribute"=["cn"]' -s 'config."group.object.classes"=["groupOfNames"]' \
-s 'config."membership.ldap.attribute"=["member"]' -s 'config."membership.attribute.type"=["DN"]' \
-s 'config."membership.user.ldap.attribute"=["uid"]' -s 'config.mode=["READ_ONLY"]' \
-s 'config."user.roles.retrieve.strategy"=["LOAD_GROUPS_BY_MEMBER_ATTRIBUTE"]' \
-s 'config."preserve.group.inheritance"=["false"]' -i)- Lancez les synchronisations et vérifiez : cinq utilisateurs importés (alice à emma) avec un
federationLink, et les groupesagentsetadministrateurs.
kcadm create "user-storage/$LDAP_ID/sync?action=triggerFullSync" -r academy -o
kcadm create "user-storage/$LDAP_ID/mappers/$MAPPER_ID/sync?direction=fedToKeycloak" -r academy -o
kcadm get users -r academy --fields username,federationLink
kcadm get groups -r academy --fields name- Constatez le mode READ_ONLY : la modification est refusée avec
error-user-attribute-read-only.
ALICE=$(kcadm get users -r academy -q username=alice -q exact=true --fields id --format csv --noquotes)
kcadm update users/$ALICE -r academy -s lastName=Autre- Connectez-vous à http://localhost:8080/realms/academy/account avec
aliceet le mot de passe de l’annuaire (password). Le mot de passe est vérifié par l’annuaire. Dans Informations personnelles, essayez de modifier votre nom : en READ_ONLY, la modification ne doit pas être possible. - Générez un fichier de reprise avec deux comptes et des empreintes PBKDF2-SHA256 (27 500 itérations), comme les produirait un ancien système.
python3 - <<'EOF'
import base64, hashlib, json, os
def compte(nom):
sel = os.urandom(16)
h = hashlib.pbkdf2_hmac("sha256", b"Reprise2026!", sel, 27500, 64)
secret = {"value": base64.b64encode(h).decode(), "salt": base64.b64encode(sel).decode(), "additionalParameters": {}}
data = {"hashIterations": 27500, "algorithm": "pbkdf2-sha256", "additionalParameters": {}}
return {"username": nom, "email": f"{nom}@example.org", "firstName": nom.capitalize(), "lastName": "Reprise",
"enabled": True, "emailVerified": True,
"credentials": [{"type": "password", "secretData": json.dumps(secret), "credentialData": json.dumps(data)}]}
json.dump({"ifResourceExists": "SKIP", "users": [compte("lucie"), compte("marc")]}, open("reprise.json", "w"), indent=2)
EOF
kcadm create partialImport -r academy -f - -o < reprise.json- Connectez-vous à la console de compte avec
lucie/Reprise2026!: la connexion réussit sans réinitialisation. - Relisez le credential de
lucie: l’empreinte a été recalculée enargon2à la connexion, selon l’algorithme par défaut du realm.
LUCIE=$(kcadm get users -r academy -q username=lucie --fields id --format csv --noquotes)
kcadm get users/$LUCIE/credentials -r academy --fields credentialDataNatif, extension ou hébergeur
Natif : fourni par Keycloak, à configurer. Extension : demande du code à maintenir (un SPI, le mécanisme de plugin de Keycloak). Hébergeur : dépend de la plateforme qui héberge Keycloak, à vérifier avec elle.
| Capacité | Verdict | Précision |
|---|---|---|
| Fédération LDAP et Active Directory (import, modes d'édition, synchronisation, mappers) | Natif | Provider LDAP fourni, avec mappers d'attributs, de groupes, de rôles et spécifiques à Active Directory. |
| Annuaire joignable uniquement depuis un réseau interne | Hébergeur | Keycloak doit ouvrir la connexion LDAP. Chez un hébergeur, cela suppose un tunnel ou un agent : modalités à vérifier avec lui. |
| Base de données applicative comme source d'utilisateurs | Extension | User Storage SPI : un provider Java qui lit (et éventuellement écrit) les comptes dans la base existante. |
| Migration au fil de l'eau (reprise du compte à la première connexion réussie) | Extension | Construite sur le User Storage SPI : valider le mot de passe auprès de l'ancien système puis créer le compte local. |
| Import d'empreintes PBKDF2 (SHA-1, SHA-256, SHA-512) et Argon2 | Natif | Formats lus nativement à l'import ; l'empreinte est recalculée avec l'algorithme du realm à la connexion suivante. |
| Import d'empreintes bcrypt, scrypt, SHA salé ou hachage maison | Extension | Demande un PasswordHashProvider spécifique (des implémentations communautaires existent pour bcrypt). |
| Identity brokering OIDC et SAML, first broker login, liaison de comptes | Natif | Flux first broker login configurable par fournisseur, mappers d'IdP, liaison depuis la console de compte. |
| Rapprochement automatique de comptes selon une règle métier (matricule, date de naissance) | Extension | Le rapprochement natif se fait sur l'e-mail ou le nom d'utilisateur ; une autre clé demande un authenticator spécifique. |
Vérifier ce que vous avez retenu
5 questions
-
L'annuaire des agents est la source de vérité et ne doit jamais être modifié par Keycloak, mais vous voulez stocker l'OTP des agents. Quelle configuration retenir ?
Avec l'import, Keycloak garde une copie locale où il peut stocker ses propres données (credentials OTP, required actions). READ_ONLY interdit toute modification des attributs mappés et des mots de passe de l'annuaire.
-
Une application historique stocke ses mots de passe en bcrypt. L'objectif est de ne pas imposer de réinitialisation. Quelles options sont réalistes ?
Keycloak 26 lit nativement PBKDF2 et Argon2, pas bcrypt. Une empreinte ne se convertit pas sans le mot de passe en clair : il faut une extension, l'une ou l'autre.
-
Un fournisseur d'identité externe renvoie un e-mail qui existe déjà dans le realm. Que fait le flux first broker login par défaut ?
Create User If Unique détecte le conflit, puis Confirm Link Existing Account et Verify Existing Account by Email ou by Re-authentication prouvent que l'usager possède le compte existant. La liaison automatique est un montage explicite et risqué.
-
Vous fédérez deux annuaires dans le même realm et un identifiant existe dans les deux. Quel est le risque ?
Keycloak cherche d'abord en base locale puis dans les providers par ordre de priorité. La documentation précise qu'il ne bascule pas vers le suivant en cas d'échec, justement à cause des doublons possibles.
-
Quelle question du questionnaire applicatif départage le mieux import d'empreintes et migration au fil de l'eau ?
Si le format est lu nativement, l'import en masse est le plus simple. Sinon, la migration au fil de l'eau suppose que l'ancien système reste disponible pour valider les mots de passe, le temps que les comptes actifs se reconnectent.