Les détails actuels concernant le système de stockage des mots de passe de Discourse sont disponibles sur discourse/docs/SECURITY.md at main · discourse/discourse · GitHub. Au moment de la rédaction de ce document, nous utilisons PBKDF2-SHA256 avec 600 000 itérations.
Dans certaines situations, vous souhaiterez peut-être exporter tous les mots de passe hachés de Discourse pour les importer dans un autre système. Par exemple, vous migrez peut-être de l’authentification intégrée de Discourse vers un système SSO personnalisé. Rappelez-vous qu’il est impossible d’extraire les mots de passe originaux de la base de données ; votre système de destination doit donc être capable d’exécuter le même algorithme de hachage avec les mêmes paramètres.
Les données relatives aux mots de passe sont stockées dans la table user_passwords, qui contient les colonnes password_hash, password_salt et password_algorithm. La colonne password_algorithm stocke le préfixe complet de l’algorithme PHC (par exemple $pbkdf2-sha256$i=600000,l=32$), qui peut varier d’un utilisateur à l’autre si le nombre d’itérations a été augmenté au fil du temps.
Vous pouvez utiliser l’explorateur de données pour exporter ces informations dans un format lisible par ordinateur :
SELECT users.id, users.username, up.password_salt, up.password_hash, up.password_algorithm
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
WHERE users.id > 0
Cela exportera les données au format natif de Discourse. Le sel est encodé en hexadécimal et le hachage du mot de passe l’est également.
Certains systèmes externes prennent en charge le format de chaîne PHC, qui vise à représenter la sortie d’une fonction de hachage de mots de passe de manière inter-algorithmes. Pour pbkdf2-sha256, cette chaîne contient le type d’algorithme, le nombre d’itérations, le sel encodé en base64 et le hachage encodé en base64. Heureusement, Postgres peut gérer tout cela pour nous dans une seule requête.
Pour générer des chaînes PHC pour chaque utilisateur Discourse, vous pouvez utiliser une requête d’explorateur de données comme celle-ci :
SELECT users.id, users.username,
concat(
up.password_algorithm,
replace(encode(up.password_salt::bytea, 'base64'), '=', ''),
'$',
replace(encode(decode(up.password_hash, 'hex'), 'base64'), '=', '')
) as phc
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
WHERE users.id > 0
Si vous utilisez Auth0, utilisez plutôt cette requête :
SELECT
user_emails.email,
users.active as email_verified,
concat(
up.password_algorithm,
replace(encode(up.password_salt::bytea, 'base64'), '=', ''),
'$',
replace(encode(decode(up.password_hash, 'hex'), 'base64'), '=', '')
) as password_hash
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
INNER JOIN user_emails
ON users.id = user_emails.user_id
AND user_emails.primary IS TRUE
AND users.id > 0
