Plain text passwords are unknown, so the "custom user federation provider" approach, suggested by Scott Rossillo in the keycloak-user Digest, Vol 22, Issue 18, seems to be feasible:
- User federation provider searches for the user in the legacy user storage on the 1st login.
- If the user is found and the password legacy hash matches the value in the legacy user storage, user credential is updated in the Keycloak storage and federation link is removed then (see code snippet below).
My question is, what would be the best way to access legacy database from within a Keycloak custom provider?
JPA datasource for the legacy database is available on the same application server, where the Keycloak server runs (EAP 6.4.3).
@Override |
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) |
{ |
for (UserCredentialModel cred : input) |
{ |
if (cred.getType().equals(UserCredentialModel.PASSWORD)) |
{ |
|
return this.updateCredential(realm, user, cred); |
|
} else |
{ |
return false; // invalid cred type |
} |
} |
return false; |
} |
|
private boolean updateCredential(RealmModel realm, UserModel user, UserCredentialModel cred) |
{ |
String password = properties.getProperty(user.getUsername()); |
if (password == null) |
return false; |
|
String encodedPassword = Digest.createPassword(cred.getValue()); |
boolean isPasswordOK = password.equals(encodedPassword); |
if (isPasswordOK) |
{ |
// save password |
session.userStorage().getUserById(user.getId(), realm).updateCredential(cred); |
// break the federation link |
session.userStorage().getUserById(user.getId(), realm).setFederationLink(null); |
} |
return isPasswordOK; |
} |