So, we’ve implemented our custom user storage provider based on a stateful EJB that interacts with a proprietary relational user database and implements all sort of interfaces (UserStorageProvider, UserLookupProvider, UserQueryProvider, CredentialInputValidator, CredentialInputUpdater). It integrates well with Keycloak so far. We’re able to sign-in, list and modify users, change passwords and verify configured password policies.
However, what does not work at the moment is the Expire Password policy, for which I’m confused what needs to be done to support this. I found out so far that o.k.a.r.UpdatePassword.evaluateTriggers() retrieves a PasswordCredentialProvider and calls getPassword() and that one either gets the password and created date from the cached user model or from a o.k.c.UserCredentialStore.
What exactly do I need to implement? Should my user storage provider implement UserCredentialStore? This is confusing since it has a lot of methods that overlap with CredentialInputValidator and CredentialInputUpdater. Or do I need my own CredentialProvider (and CredentialProviderFactory)?
Turns out to easier than expected. In the implemented CredentialInputValidator.isValid() just do
int daysToExpire = realm.getPasswordPolicy().getDaysToExpirePassword();
if (daysToExpire > 0) {
if (isPasswordExpired(/*...*/)) {
userModel.addRequiredAction(RequiredAction.UPDATE_PASSWORD);
}
}
Hi, Can you please tell me what should be the code inside addRequiredAction method?
I override AbstractUserAdapter class and inside that addRequiredAction method looks like below. It throws read only error if I do not override this method. I have already implemented CredentialInputUpdater
@Override
public void addRequiredAction(RequiredAction action) {
if (action == null) return;
String actionName = action.name();
if (actionName == RequiredAction.UPDATE_PASSWORD.name())
return;
super.addRequiredAction(action);
}
This is making calls to this but the user is able to log in without any error.