How to import users from another system or IDM?

Continuing the discussion from How to best import users from legacy application?.

All the other topics posted here have no answers on how to import other user data. There are examples online of how to write custom SPIs to do a single user migration on the fly when the user logs in but this assumes that your other provider will always be available. Is there a way to bulk migrate users?

The last comment in the link above states that you could create a user import JSON and have Keycloak import old users in this fashion. Is this still a valid way or the way to do something like this?

I have tried this with the newer User JSON import format but it is not working and I am not sure if I am just doing it incorrectly or if it just doesn’t work anymore.

See example of format I tried:

{
	"realm": "realmName",
	"users": [
		{
			"username": "testuser@example.com",
			"email": "testuser@example.com",
			"enabled": true,
			"totp": false,
			"emailVerified": true,
			"firstName": "Test",
			"lastName": "User",
			"attributes": {
				"phoneNumber": "3456567678",
				"preferredMethodOfCommunication": "email",
				"securityQuestion1": [
					"In what city did you meet your spouse/significant other?"
				],
				"securityAnswer1": ["test"]
			},
			"credentials": [
				{
					"type": "password",
					"algorithm": "bcrypt",
					"hashedSaltedValue": "$2a...."
				}
			],
			"disableableCredentialTypes": [],
			"requiredActions": [],
			"realmRoles": ["default-roles-realmName"],
			"notBefore": 0,
			"groups": []
		},

Any help would be appreciated.

Sorry to repost, but I added this after your message. I think this is the best way to just-in-time migration of users. How to best import users from legacy application? - #9 by xgp

It’s ok. I guess I should have waited a little bit.

The only issue with the just-in-time migration is going to be that you will either have to always keep that legacy DB (provider) up and running or create some cutoff time limit of when to mass migrate the rest of the users and have them change their password. Correct?

I did see the plugin in my research but thank you again for putting it on my radar.

That’s right. I’ve implemented this for a few customers, and it really depends on your use case. Some of them chose to leave it in place. Others sent an email asking users to log in within a specific amount of time. Others did a manual check after some time period, and just manually created account in Keycloak for the “missing” users, who could do a “reset password” (assuming they have an email for the user).

I’ve also done a one-time bulk import from existing user data via the JSON import. This does work, but needs a bit effort to get all the attributes right. Especially regarding the passwords - if the source system has another hashing algorithm (other than pbkdf2) used, you will have to provide this as a hashing algorithm provider in Keycloak first.

Hey @dasniko. That is good to know. Given my example above does anything look out of place?

I have copied the same fields that my manual data export created for test users so all of it basically looks how my exported data looks except for this credential part.

Exported data example:

{
	"id": "",
	"type": "password",
	"createdDate": 1684539012411,
	"secretData": ",
	"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
}

How should the imported credentials look in comparison to the data above?

And also, like you said, the hashing algorithm I have is bcrypt and not pbkdf2. Do you have a resource for how I would provide the hashing algorithm to Keycloak?

If I added a the bcrypt provider I found here how do I let Keycloak know that it exists to use other than just placing in the providers? GitHub - leroyguillaume/keycloak-bcrypt: Add BCrypt password provider in Keycloak

Your credential example looks like the ones I have here in my environment (except that secretData has also a value (serialized JSON like credentialData), and also the id is filled!

If Keycloak just should use the bcrypt algorithm to compare stored password hashes, you don’t have to do anything else than putting the JAR into the providers folder. If Keycloak should use bcrypt also to create hashes on newly created/updated passwords, you’ll have to configure it as a “Password Policy” (there’s a “Hashing algorithm” policy available). It sounds a bit strange that this is a policy, but it is like it is.