1

I want to create a user using a password that has already been hashed (using argon2). This is to validate the user migration process from my application's database to Keycloak.

I went to Authentication > Policies and configured the Hashing Algorithm as argon2. This way, when I create a "regular" password, it is automatically hashed to argon2.

Keycloak Authentication Config

I generated a hash using argon2 on the argon2.online platform. The parameters I used were the same as the default ones in Keycloak:

  • Plain Text Input: password
  • Salt: abcd1234
  • Parallelism Factor: 1
  • Memory Cost: 7168
  • Iterations: 5
  • Hash Length: 32

Using the Argon2id, the generated output was: $argon2id$v=19$m=7168,t=5,p=1$YWJjZDEyMzQ$M2pBlbaI2O0icDQslGeP1dTAVUxdnzx7GZr9N1Fdd04

Hash Validation

I am using the following code to create a random user and then login:

import keycloak
import json
from datetime import datetime

password = 'password'

argon2_data = {
    'plain_text_input': password,
    'salt': 'abcd1234',
    'parallelism': 1,
    'memory_cost': 7168,
    'iterations': 5,
    'hash_length': 32,
    'hash': '$argon2id$v=19$m=7168,t=5,p=1$YWJjZDEyMzQ$M2pBlbaI2O0icDQslGeP1dTAVUxdnzx7GZr9N1Fdd04',
    'version': '1.3',
}

argon2_data['hash_parts'] = argon2_data['hash'].split('$')

def create_user():

    ts = datetime.now().strftime("%H%M%S")

    username = f"john{ts}"

    basic_credentials = {
        'type': 'password',
        'temporary': False,
        'value': password,
    }

    argon2_credentials = {
        'type': 'password',
        'temporary': False,
        'secretData': json.dumps({
            'value': argon2_data['hash_parts'][-1],
            'salt': argon2_data['hash_parts'][-2],
        }),
        'credentialData': json.dumps({
            'hashIterations': argon2_data['iterations'],
            'algorithm': 'argon2',
            'additionalParameters': {
                'hashLength': [str(argon2_data['hash_length'])],
                'memory': [str(argon2_data['memory_cost'])],
                'type': ['id'],
                'version': [argon2_data['version']],
                'parallelism': [str(argon2_data['parallelism'])],
            }
        })
    }

    user_data = {
        'attributes': {
            'custom_key': 'custom_value'
        },
        'credentials': [
            #basic_credentials,
            argon2_credentials,
        ],
        'username': username,
        'firstName': 'John',
        'lastName': 'Doe',
        'email': f'{username}@doe.com.br',
        'emailVerified': True,
        'enabled': True
    }

    print(user_data)

    keycloak.create_user(user_data)

    return user_data

user = create_user()

keycloak.test_login(user['username'], password)

Creating the user using basic_credentials allows me to log in successfully immediately. However, creating the user using argon2_credentials causes the login to return the error "invalid user credentials".

What could I be doing wrong?

1
  • Have you checked the Keycloak DB? Is the hashed value saved as the User's PW what you expect it to be? If you perform a full realm export from keycloak, you also get the credential hashes, you could compare those to what your input was to see where you went wrong. Commented Nov 18 at 9:59

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.