Migration d'un IdP legacy vers Auth0 : méthodologie complète
Migrer depuis un système d'authentification maison ou un LDAP vers Auth0. Analyse des risques, plan de migration et gestion des mots de passe.
Par Auth0.Expert · 2025-05-08 · 12 min de lecture
Migration d'un IdP legacy vers Auth0
TL;DR
Migrer depuis un système d'authentification maison ou LDAP vers Auth0 est le projet IAM le plus risqué. Ce guide présente la méthodologie éprouvée pour le faire sans déconnecter vos utilisateurs.
---
Analyse des systèmes legacy fréquents
Voici un tableau comparatif des principaux systèmes legacy et leur compatibilité de migration vers Auth0.
| Système | Complexité migration | Spécificité | |---------|---------------------|-------------| | Auth maison (PHP/Node) | Élevée | Mots de passe en md5/sha1 = reset obligatoire | | Django auth | Moyenne | PBKDF2 compatible avec Auth0 | | LDAP/AD | Moyenne | Custom Database Connection | | Devise (Rails) | Faible | bcrypt compatible | | Spring Security | Moyenne | BCrypt ou Argon2 | | Firebase Auth | Moyenne | Export/Import possible | | Cognito | Moyenne | Voir article dédié |
---
Phase 0 : Inventaire
Avant de démarrer, il est essentiel de répondre à ces questions sur votre base utilisateurs pour mesurer l'effort et les risques de la migration.
# Questions à répondre avant de commencer
# 1. Combien d'utilisateurs ?
SELECT COUNT(*) FROM users WHERE deleted_at IS NULL;
# 2. Quelle algorithme de hash ?
SELECT DISTINCT hash_algorithm FROM users LIMIT 10;
# 3. Quelle proportion a un email vérifié ?
SELECT
COUNT(*) as total,
SUM(CASE WHEN email_verified THEN 1 ELSE 0 END) as verified,
ROUND(100.0 * SUM(CASE WHEN email_verified THEN 1 ELSE 0 END) / COUNT(*), 1) as pct_verified
FROM users;
# 4. Activité récente (pour prioriser)
SELECT
COUNT(*) as total,
SUM(CASE WHEN last_login > NOW() - INTERVAL '90 days' THEN 1 ELSE 0 END) as active_90d,
SUM(CASE WHEN last_login > NOW() - INTERVAL '365 days' THEN 1 ELSE 0 END) as active_1y,
SUM(CASE WHEN last_login IS NULL THEN 1 ELSE 0 END) as never_logged
FROM users;
---
Phase 1 : Migration des profils (sans mots de passe)
Cette étape consiste à importer les profils utilisateurs dans Auth0, sans le mot de passe, pour préparer l'arrivée des utilisateurs.
# Migrer d'abord les profils → les utilisateurs existaient dans Auth0
# avant même de se connecter
async def migrate_profiles_batch(users: list, connection_id: str):
"""Import des profils utilisateurs sans mots de passe."""
auth0_users = []
for user in users:
auth0_user = {
"email": user["email"],
"email_verified": user.get("email_verified", False),
"name": f"{user.get('first_name', '')} {user.get('last_name', '')}".strip(),
"given_name": user.get("first_name"),
"family_name": user.get("last_name"),
"app_metadata": {
"legacy_id": str(user["id"]),
"legacy_created_at": user["created_at"].isoformat() if user.get("created_at") else None,
"migrated_profile": True,
"migrated_at": datetime.utcnow().isoformat(),
}
}
auth0_users.append(auth0_user)
# Auth0 Jobs API : import en masse
# Le mot de passe n'est PAS inclus → utilisateurs seront invités à définir leur MDP
# OU on utilise une Custom Database Connection pour la migration lazy
return await create_import_job(auth0_users, connection_id)
Ce code importe un lot de profils utilisateurs dans Auth0 sans inclure les mots de passe, stockant notamment les métadonnées liées à la migration.
---
Phase 2 : Custom Database Connection pour migration lazy
Ici, on va permettre la migration “à la volée” : les utilisateurs se connectent avec leurs anciens identifiants, Auth0 valide désormais auprès de l’IdP legacy, puis migre leur compte.
// Login Script : vérifier dans legacy, créer dans Auth0
exports.login = async function (email, password, callback) {
const crypto = require('crypto');
const bcrypt = require('bcryptjs');
// Appeler votre API legacy pour vérifier les credentials
try {
const resp = await fetch(`${configuration.LEGACY_API}/auth/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
const { success, user } = await resp.json();
if (!success || !user) {
return callback(null, null); // Mauvais credentials
}
// Hash du mot de passe en SHA-1 (legacy) → bcrypt (Auth0)
// Auth0 va automatiquement migrer vers bcrypt
return callback(null, {
user_id: user.id.toString(),
email: user.email,
email_verified: user.email_verified || false,
given_name: user.first_name,
family_name: user.last_name,
});
} catch (err) {
return callback(err);
}
};
// Change Password Script
exports.changePassword = async function (email, newPassword, callback) {
// Changer dans le système legacy (pour la période de transition)
try {
await fetch(`${configuration.LEGACY_API}/users/password`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password: newPassword }),
});
return callback(null, true);
} catch (err) {
return callback(err);
}
};
Ce script assure la connexion et la mise à jour de mot de passe en interrogeant directement l'API legacy, pour garantir une bascule transparente lors des premiers logins.
---
Gestion des algorithmes de hash legacy
Si plusieurs algorithmes de hash coexistent, il faut tous les gérer pour garantir la migration automatique de chaque utilisateur.
// Auth0 Custom Database : tester les hashs legacy
// MD5 (dangereux, mais fréquent dans les vieux systèmes)
function verifyMd5(password, hash) {
const crypto = require('crypto');
return crypto.createHash('md5').update(password).digest('hex') === hash;
}
// SHA-256 avec salt
function verifySha256(password, hash, salt) {
const crypto = require('crypto');
const computed = crypto.createHash('sha256')
.update(salt + password)
.digest('hex');
return computed === hash;
}
// Argon2 (moderne)
async function verifyArgon2(password, hash) {
const argon2 = require('argon2');
return await argon2.verify(hash, password);
}
// Dans le login script
exports.login = async function (email, password, callback) {
const user = await getLegacyUser(email);
if (!user) return callback(null, null);
let valid = false;
switch (user.hash_algo) {
case 'md5': valid = verifyMd5(password, user.password_hash); break;
case 'sha256': valid = verifySha256(password, user.password_hash, user.salt); break;
case 'bcrypt':
const bcrypt = require('bcryptjs');
valid = await bcrypt.compare(password, user.password_hash);
break;
case 'argon2': valid = await verifyArgon2(password, user.password_hash); break;
}
if (!valid) return callback(null, null);
return callback(null, { user_id: user.id, email: user.email });
};
Ce code offre un contrôle multi-algorithme pour comparer les mots de passe entrants selon le hash stocké lors de la migration.
---
Rollout : coupure du système legacy
Cet exemple de planning illustre comment organiser la transition progressive vers Auth0 pour garantir l’absence de coupure d’accès.
Semaine 1-8 : Migration lazy active
Tous les logins passent par Custom DB Connection (auth legacy)
À chaque login réussi → compte Auth0 créé avec MDP bcrypt
Semaine 9 : Vérifier le % de comptes migrés
> 80% actifs migrés → continuer
< 80% → continuer la migration lazy
Semaine 10 : Migrer les comptes restants en batch
Reset de mot de passe pour les comptes non actifs
Semaine 11 : Basculer la connexion de Custom DB vers Database Native
(les mots de passe sont maintenant stockés dans Auth0)
Semaine 12 : Désactiver le système legacy
Garder le système en lecture seule 30 jours (rollback)
Ce déroulé progressif permet de migrer 100% des comptes tout en offrant une période de fallback en cas d’incident.
---
KPIs de migration à suivre
Mesurez l’avancée de votre migration grâce à ces requêtes SQL qui suivent le nombre de profils basculés quotidiennement.
-- Suivi quotidien de la migration
SELECT
DATE(created_at) as migration_date,
COUNT(*) as migrated_that_day,
SUM(COUNT(*)) OVER (ORDER BY DATE(created_at)) as total_migrated,
(SELECT COUNT(*) FROM legacy_users) as total_to_migrate,
ROUND(100.0 * SUM(COUNT(*)) OVER (ORDER BY DATE(created_at)) /
(SELECT COUNT(*) FROM legacy_users), 1) as progress_pct
FROM auth0_users -- Table de suivi de migration
WHERE app_metadata->>'migrated_profile' = 'true'
GROUP BY 1
ORDER BY 1;
Ce rapport permet d’obtenir un taux de progression clair pour piloter et ajuster la migration.
---
> 🔄 Migration IdP legacy : nous avons migré des systèmes d'authentification de toutes technologies (PHP, .NET, Java, Ruby, Python) vers Auth0 avec zéro perte d'accès.
📞 +33 1 23 45 67 89 · 📧 [email protected]
Autres articles
- Auth0 et OAuth 2.0 : architecture complète pour comprendre les flux d'autorisation
- OpenID Connect sur Auth0 : ID Token, UserInfo et discovery endpoint expliqués
- Configurer SAML 2.0 avec Auth0 : guide complet pour l'entreprise
- Migrer des Rules vers les Auth0 Actions : guide pas à pas
- Architecture multi-tenant avec Auth0 : organisations, isolation et bonnes pratiques
- Validation des JWT Auth0 : RS256 vs HS256, JWKS et pièges communs
- Concevoir son architecture de tenants Auth0 : dev, staging, prod
- Configurer un domaine personnalisé Auth0 : login.votredomaine.com étape par étape