daniel-frak / keycloak-user-migration

A Keycloak plugin for migrating users from legacy systems
MIT License
304 stars 136 forks source link

Bypassing password complexity requirements on import #181

Closed dsputnikk closed 4 months ago

dsputnikk commented 4 months ago

Hi,

Was looking for some advice really. I have a use case where I need to start migrating users from SQL to KeyCloak and this provider works perfect. The project demands that a more stricter password complexity requirement be enforced on KC, then that which was set in SQL land (by the application being migrated to KeyCloak auth).

Say the new password complexity in KC limited the amount of chars to 10, but I have a password in SQL of 12 chars.. the import process fails because it does not meet the password complexity requirements of KC.

I see this method:

image

And it seems that when PasswordPolicy isn't met, it will skip updating the credential and then its supposed to then set UPDATE_PASSWORD and force the user into a new password flow, but that doesn't seem to occur. Furthermore, the lack of a password breaks some other areas/flows/providers for me.

When I try to remove or override PasswordDoesNotBreakPolicy to be true and the code proceeds to userModel.credentialmanager().updateCredential - the problem persists. I believe this is because credentialmanager (a base implement of KC as opposed to this repos), validates password complexity yet again?

It also seems impossible to overwrite anything in "CredentialInput input" that is passed into this method with a password of my choice (and then set UPDATE_PASSWORD).

I looked at KC API docs and eventually landed on attempting to make my own CredentialInput object, but for that I need a new UserCredentialModel (https://www.keycloak.org/docs-api/22.0.4/javadocs/org/keycloak/models/UserCredentialModel.html). It has a nested class of type PasswordUserCredentialModel. When I attempt to create a PasswordUserCredentialModel, mvn build says that it is private and can't be used here.

So I'm in a bit of a loss. I want to keep password policy requirements on, but I still need to successfully import users who do not meet it (yet) and take them thru a password update process. Since other things don't seem to like not having a password set, I just want to set it to a random string that meets my new password complexity requirements (thereby allowing the process to finish) and immediately take the user thru a password update process.

Any ideas on how I might accomplish this?

dsputnikk commented 4 months ago

Solved this by implementing a "FakeCredential" class that implements the ClassInput interface and passing my own credentials.