If you're looking into migrating to Keycloak as your auth provider, you've probably wondered how to import your current existing database's users, and more importantly those precious bcrypt hashed passwords. This short guide will show you the necessary steps.
I assume you already have a Keycloak instance running on your local machine at port 8080. The Keycloak version I'm using at time of writing is 8.2.
If you haven't already, install keycloak-bcrypt and the jbcrypt
library on your keycloak instance. I've gathered the steps into a single script, I'm running Keycloak in a Docker container so the file locations might be different for you:
KEYCLOAK_HOME=~/keycloak
curl https://repo1.maven.org/maven2/org/mindrot/jbcrypt/0.4/jbcrypt-0.4.jar > jbcrypt-0.4.jar
$KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.mindrot.jbcrypt --resources=jbcrypt-0.4.jar"
curl -L https://github.com/leroyguillaume/keycloak-bcrypt/releases/download/1.2.0/keycloak-bcrypt-1.2.0.jar > $KEYCLOAK_HOME/standalone/deployments/keycloak-bcrypt-1.2.0.jar
Now you should restart Keycloak.
You can start using the bcrypt hashing algorithm by setting it up under Authentication (the other settings are optional):
We'll write our migration in JavaScript. You'll have to create a new package (or use your existing migration framework) to run the migration in.
Install the Keycloak admin client for node.js with:
npm i --save keycloak-admin
You're all set to start migrating! Edit the below code snippet to your needs by changing the environments and adding attributes, roles or groups as you see necessary.
import KeycloakAdminClient from 'keycloak-admin';
const {
AUTH_URL = 'http://localhost:8080/auth',
AUTH_REALM_NAME = 'myRealmName',
AUTH_ADMIN_USERNAME = 'admin',
AUTH_ADMIN_PASSWORD = 'admin',
AUTH_ADMIN_CLIENT = 'admin-cli',
AUTH_ADMIN_SECRET = 'jriozejrioezjriorez',
// ^ needed if your admin-cli client is set to confidential
} = process.env;
const authClient = new KeycloakAdminClient({
baseUrl: AUTH_URL, // http://localhost:8080/auth
realmName: AUTH_REALM_NAME,
});
const startMigration = async ({ database }) => {
await authClient.auth({
username: AUTH_ADMIN_USERNAME,
password: AUTH_ADMIN_PASSWORD,
clientId: AUTH_ADMIN_CLIENT, // probably admin-cli
// only needed if your admin client is set to confidential
clientSecret: AUTH_ADMIN_SECRET,
grantType: 'password',
});
const existingUsers = await database.users.find();
for (let existingUser of existingUsers) {
const user = {
realm: AUTH_REALM_NAME,
credentials: [
{
algorithm: 'bcrypt',
hashedSaltedValue: existingUser.password, // the bcrypt-hashed password
hashIterations: 10,
type: 'password',
},
],
email: existingUser.email,
username: existingUser.email,
emailVerified: true,
enabled: true,
};
await authClient.users.create(user);
}
};
Et voilà. Your existing users were migrated to Keycloak and they'll still be able to log in with the same password as they would before.
Until next time!
Top comments (2)
I checked your hash algoritm correctly in keycloak but I have some questions:
In your code you use this implementation about bcrypt-0.9.0.jar but you install this dependencie jbcrypt-0.4.jar and register like a module in keycloak, i don't understand this.
Why I must install any module like jbcrypt-0.4.jar in keycloak. If the dependency bcrypt-0.9.0.jar it's inside keycloak-bcrypt.jar?
for whoever is reading this now, hashedSaltedValue is now deprecated