Skip to content

Instantly share code, notes, and snippets.

@yashasolutions
Last active September 4, 2024 10:11
Show Gist options
  • Save yashasolutions/edb93f104572e8c73b9dd0db5f0581af to your computer and use it in GitHub Desktop.
Save yashasolutions/edb93f104572e8c73b9dd0db5f0581af to your computer and use it in GitHub Desktop.
# this is using python-keycloak package
# the goal is to move the existing users with their django passwords into keycloak
# so that it is as seemless as possible for the users when integrating the SSO solution
#
# This is a working solution
# Important to note the salt encoding using utf8 else, it wont work
# and the name of the algorithm is different in django and in keycloak (small difference but important one)
def create_keycloak_user_from_django(django_user, keycloak_admin):
django_password = django_user.password
algo, iteration, salt, hashed_password = django_password.split('$')
salt64 = base64.b64encode(salt.encode('utf-8')).decode('utf-8')
credential_data = {
"algorithm": algo.replace('_', '-'), # replace pbkdf2_sha256 (django naming) with pbkdf2-sha256 (keycloak)
"hashIterations": int(iteration),
}
secret_data = {
"salt": salt64,
"value": hashed_password,
}
try:
u = keycloak_admin.create_user({
"username": django_user.email,
"email": django_user.email,
"enabled": True,
"firstName": django_user.first_name,
"lastName": django_user.last_name,
"credentials": [{
"type": "password",
"credentialData": json.dumps(credential_data),
"secretData": json.dumps(secret_data),
"temporary": False,
}],
"emailVerified": True,
})
print(f'User created: {u}')
return u
except Exception as e:
print(f'Error creating user: {e}')
return None
@yashasolutions
Copy link
Author

This code generate the user but when trying to login, we keep getting invalid password.

@jahan-paisley
Copy link

jahan-paisley commented Sep 2, 2024

You need to capture the user's password upon successful login and insert it into Keycloak using the plain password provided by the user. Of course, Keycloak will then store the hashed version.

I'm the Stack Overflow guy on Upwork :-) Let me know if you need further help.

@yashasolutions
Copy link
Author

You need to capture the user's password upon successful login and insert it into Keycloak using the plain password provided by the user. Of course, Keycloak will then store the hashed version.

I'm the Stack Overflow guy on Upwork :-) Let me know if you need further help.

nice!
I just got someone working on this but I'll bookmark your upwork :)
I am looking for a way to do that a batch upload in the background without having to have people change password.

@jahan-paisley
Copy link

You need to capture the user's password upon successful login and insert it into Keycloak using the plain password provided by the user. Of course, Keycloak will then store the hashed version.
I'm the Stack Overflow guy on Upwork :-) Let me know if you need further help.

nice! I just got someone working on this but I'll bookmark your upwork :) I am looking for a way to do that a batch upload in the background without having to have people change password.

Cool, yeah that would do the trick although in a gradual process. Cheers mate!

@AbhijeetAAA
Copy link

AbhijeetAAA commented Sep 4, 2024

The request body you are sending is incorrect. Please use below request body, few changes in "credentials" object. If you face any issue you can reach out to me on Abhijeet G

{
"username": django_user.email,
"email": django_user.email,
"enabled": True,
"firstName": django_user.first_name,
"lastName": django_user.last_name,
"credentials": [{
"type": "password",
"value": "{{password-of-user-in-plain-text}}",
"temporary": False,
}],
"emailVerified": True,
"enabled": True
}

@yashasolutions
Copy link
Author

The request body you are sending is incorrect. Please use below request body, few changes in "credentials" object. If you face any issue you can reach out to me on Abhijeet G

{ "username": django_user.email, "email": django_user.email, "enabled": True, "firstName": django_user.first_name, "lastName": django_user.last_name, "credentials": [{ "type": "password", "value": "{{password-of-user-in-plain-text}}", "temporary": False, }], "emailVerified": True, "enabled": True }

thanks - you're correct this is likely to work for new users.
Here the challenge was to transfer existing passwords.
Issue solved by the way, there was an error with the encoding of the salt and the name of the algorithm is slightly different in django than in keycloak

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment