Created
October 4, 2024 16:49
-
-
Save TimKochDev/b93611c3e2f14ccca7612729214a0b8b to your computer and use it in GitHub Desktop.
Import users with password hashes to Keycloak. Watch your encodings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Before moving to Keycloak, I used the following code to generate user credentials | |
const crypto = require("crypto"); | |
const salt = crypto.randomBytes(16).toString("hex"); | |
const hash = crypto | |
.pbkdf2Sync(password, this.salt, 10000, 64, "sha512") | |
.toString("hex"); | |
// HEADS UP: Even though the salt was created as random bytes and then converted to its hex representation, | |
// the hashing function interpreted it as UTF-8. So this yields the same hash as the following: | |
const sameHash = crypto | |
.pbkdf2Sync(password, Buffer.from(this.salt, "utf-8"), 10000, 64, "sha512") | |
.toString("hex"); | |
// So to migrate a user to Keycloak I did the following | |
const response = await keycloakClient | |
.post(`/admin/realms/${KEYCLOAK_REALM}/users`, { | |
credentials: | |
user.salt && user.hash | |
? [ | |
{ | |
credentialData: JSON.stringify({ // Keycloak requires this to be stringified. Don't know why | |
algorithm: "pbkdf2-sha512", | |
hashIterations: 10000, | |
}), | |
secretData: JSON.stringify({ // Keycloak requires this to be stringified. Don't know why | |
salt: Buffer.from(user.salt, "utf-8").toString("base64"), // Keycloak stores the salt in base64 | |
value: Buffer.from(user.hash, "hex").toString("base64"), // Keycloak stores the hash in base64 | |
}), | |
type: "password", | |
}, | |
] | |
: undefined, | |
email: user.email, | |
emailVerified: true, | |
enabled: true, | |
}) | |
const locationHeader = response.headers.location; | |
const userId = locationHeader.substring(locationHeader.lastIndexOf("/") + 1); | |
// For your reference, this is how Keycloak would hash using pbdf2_sha512 implemented in NodeJS | |
function hashLikeKeycloak(salt) { | |
return crypto | |
.pbkdf2Sync(plaintext, Buffer.from(salt, "base64"), 10000, 64, "sha512") | |
.toString("base64"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment