commit
7c0c48da01
4 changed files with 46 additions and 4 deletions
|
@ -73,6 +73,16 @@ public class Pbkdf2PasswordHashProvider implements PasswordHashProvider {
|
||||||
credential.setValue(encodedPassword);
|
credential.setValue(encodedPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode(String rawPassword, int iterations) {
|
||||||
|
if (iterations == -1) {
|
||||||
|
iterations = defaultIterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] salt = getSalt();
|
||||||
|
return encode(rawPassword, iterations, salt);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean verify(String rawPassword, CredentialModel credential) {
|
public boolean verify(String rawPassword, CredentialModel credential) {
|
||||||
return encode(rawPassword, credential.getHashIterations(), credential.getSalt()).equals(credential.getValue());
|
return encode(rawPassword, credential.getHashIterations(), credential.getSalt()).equals(credential.getValue());
|
||||||
|
|
|
@ -29,5 +29,10 @@ public interface PasswordHashProvider extends Provider {
|
||||||
|
|
||||||
void encode(String rawPassword, int iterations, CredentialModel credential);
|
void encode(String rawPassword, int iterations, CredentialModel credential);
|
||||||
|
|
||||||
|
default
|
||||||
|
String encode(String rawPassword, int iterations) {
|
||||||
|
return rawPassword;
|
||||||
|
}
|
||||||
|
|
||||||
boolean verify(String rawPassword, CredentialModel credential);
|
boolean verify(String rawPassword, CredentialModel credential);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,12 @@ import org.keycloak.authentication.AbstractFormAuthenticator;
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
import org.keycloak.credential.CredentialInput;
|
import org.keycloak.credential.CredentialInput;
|
||||||
|
import org.keycloak.credential.CredentialModel;
|
||||||
|
import org.keycloak.credential.hash.PasswordHashProvider;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
|
import org.keycloak.models.PasswordPolicy;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
@ -83,8 +86,32 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
return challengeResponse;
|
return challengeResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void runDefaultDummyHash(AuthenticationFlowContext context) {
|
||||||
|
PasswordHashProvider hash = context.getSession().getProvider(PasswordHashProvider.class, PasswordPolicy.HASH_ALGORITHM_DEFAULT);
|
||||||
|
hash.encode("dummypassword", PasswordPolicy.HASH_ITERATIONS_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void dummyHash(AuthenticationFlowContext context) {
|
||||||
|
PasswordPolicy policy = context.getRealm().getPasswordPolicy();
|
||||||
|
if (policy == null) {
|
||||||
|
runDefaultDummyHash(context);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
PasswordHashProvider hash = context.getSession().getProvider(PasswordHashProvider.class, policy.getHashAlgorithm());
|
||||||
|
if (hash == null) {
|
||||||
|
runDefaultDummyHash(context);
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
hash.encode("dummypassword", policy.getHashIterations());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public boolean invalidUser(AuthenticationFlowContext context, UserModel user) {
|
public boolean invalidUser(AuthenticationFlowContext context, UserModel user) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
|
dummyHash(context);
|
||||||
context.getEvent().error(Errors.USER_NOT_FOUND);
|
context.getEvent().error(Errors.USER_NOT_FOUND);
|
||||||
Response challengeResponse = invalidUser(context);
|
Response challengeResponse = invalidUser(context);
|
||||||
context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
|
context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
|
||||||
|
@ -144,15 +171,15 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invalidUser(context, user)){
|
if (invalidUser(context, user)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validatePassword(context, user, inputData)){
|
if (!validatePassword(context, user, inputData)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!enabledUser(context, user)){
|
if (!enabledUser(context, user)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue