DEV Community

Brecht Carnewal
Brecht Carnewal

Posted on • Updated on

Import your bcrypt hashed user passwords into Keycloak

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



Enter fullscreen mode Exit fullscreen mode

Now you should restart Keycloak.

You can start using the bcrypt hashing algorithm by setting it up under Authentication (the other settings are optional):

Keycloak Bcrypt setup

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);
  }
};



Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
masalinas profile image
Miguel Angel Salinas Gancedo

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?

Collapse
 
yashasolutions profile image
Yasha

for whoever is reading this now, hashedSaltedValue is now deprecated