implement actual functionality

This commit is contained in:
Julian Picht
2019-09-14 13:58:36 +02:00
parent 8626ac63b0
commit 82894e3368
5 changed files with 1311 additions and 26 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
target

View File

@@ -57,6 +57,11 @@
<version>6.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>6.0.1</version>
</dependency>
</dependencies>
<build>
<pluginManagement>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
package com.github.jpicht.keycloak.policy;
/*
* Copyright 2019 Julian Picht
*
@@ -16,25 +14,34 @@ package com.github.jpicht.keycloak.policy;
* limitations under the License.
*/
package com.github.jpicht.keycloak.policy;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import org.jboss.logging.Logger;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.policy.PasswordPolicyConfigException;
import org.keycloak.policy.PasswordPolicyProvider;
import org.keycloak.policy.PolicyError;
import org.jboss.logging.Logger;
import org.keycloak.theme.Theme;
public class GroupPasswordPolicyProvider implements PasswordPolicyProvider {
private static final Logger logger = Logger.getLogger(GroupPasswordPolicyProvider.class);
private static final String ERROR_MESSAGE = "invalidGroupPasswordPolicy";
private KeycloakContext context;
private KeycloakSession session;
public GroupPasswordPolicyProvider(KeycloakContext context) {
this.context = context;
public GroupPasswordPolicyProvider(KeycloakSession session) {
this.session = session;
}
@Override
@@ -42,23 +49,114 @@ public class GroupPasswordPolicyProvider implements PasswordPolicyProvider {
return null;
}
private class PrefixRemover {
public LinkedList<String> messages;
public String prefix;
PrefixRemover() {
messages = new LinkedList<>();
prefix = null;
}
void add(String str) {
messages.add(str);
if (prefix == null) {
prefix = str;
return;
}
if (str.startsWith(prefix)) {
return;
}
List<String> strParts = Arrays.asList(str.split(" "));
List<String> prefixParts = Arrays.asList(prefix.split(" "));
int minLength = Math.min(strParts.size(), prefixParts.size());
for (int i = 0; i < minLength; i++) {
if (!strParts.get(i).equals(prefixParts.get(i))) {
prefix = String.join(" ", prefixParts.subList(0, i));
break;
}
}
}
public String getPrefix() {
return prefix;
}
public LinkedList<String> getMessagesWithoutPrefix() {
LinkedList<String> out = new LinkedList<>();
for (String msg : messages) {
out.add(msg.substring(prefix.length()));
}
return out;
}
}
@Override
public PolicyError validate(RealmModel realm, UserModel user, String password) {
String groupAttribute = context.getRealm().getPasswordPolicy().getPolicyConfig(GroupPasswordPolicyProviderFactory.ID);
logger.infof("groupAttribute %s", groupAttribute);
logger.infof("user %s", user.getUsername());
String groupAttribute = realm.getPasswordPolicy().getPolicyConfig(GroupPasswordPolicyProviderFactory.ID);
logger.debugf("groupAttribute %s", groupAttribute);
logger.debugf("user %s", user.getUsername());
LinkedList<PolicyError> list = new LinkedList<>();
for (GroupModel group : user.getGroups()) {
logger.infof("group %s", group.getName());
for (String policy : group.getAttribute(groupAttribute)) {
//factorPolicy(policy).validate();
logger.info(policy);
logger.debugf("group %s", group.getName());
for (String policyString : group.getAttribute(groupAttribute)) {
logger.infof("adding group password policy: %s", policyString);
PasswordPolicy policy = parsePolicy(policyString);
list.addAll(validateSubPolicy(policy, realm, user, password));
}
}
realm.getPasswordPolicy();
logger.infof("account theme ", context.getRealm().getAccountTheme());
logger.infof("admin theme ", context.getRealm().getAdminTheme());
logger.infof("login theme ", context.getRealm().getLoginTheme());
return new PolicyError("nope");
if (list.isEmpty()) {
return null;
}
Properties messageProps;
try {
messageProps = session.theme().getTheme(Theme.Type.ACCOUNT).getMessages(session.getContext().resolveLocale(user));
} catch (IOException e) {
return new PolicyError(e.getLocalizedMessage());
}
PrefixRemover messages = new PrefixRemover();
for (PolicyError e : list) {
messages.add(MessageFormat.format(messageProps.getProperty(e.getMessage(), e.getMessage()), e.getParameters()));
}
return new PolicyError(messages.getPrefix() + String.join("\n", messages.getMessagesWithoutPrefix()));
}
private PasswordPolicy parsePolicy(String policy) {
LinkedList<PasswordPolicyProvider> list = new LinkedList<>();
PasswordPolicy parsedPolicy = PasswordPolicy.parse(session, policy);
return parsedPolicy;
}
private LinkedList<PolicyError> validateSubPolicy(PasswordPolicy policy, RealmModel realm, UserModel user, String password) {
RealmModel realRealm = session.getContext().getRealm();
LinkedList<PolicyError> list = new LinkedList<>();
try {
for (String id : policy.getPolicies()) {
FakeRealm fakeRealm = new FakeRealm();
fakeRealm.setPasswordPolicy(policy);
session.getContext().setRealm(fakeRealm);
PasswordPolicyProvider provider = session.getProvider(PasswordPolicyProvider.class, id);
PolicyError error = provider.validate(realm, user, password);
if (null != error) {
list.add(error);
}
}
} finally {
session.getContext().setRealm(realRealm);
}
return list;
}
@Override

View File

@@ -1,6 +1,3 @@
package com.github.jpicht.keycloak.policy;
/*
* Copyright 2019 Julian Picht
*
@@ -17,6 +14,8 @@ package com.github.jpicht.keycloak.policy;
* limitations under the License.
*/
package com.github.jpicht.keycloak.policy;
import com.google.auto.service.AutoService;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
@@ -36,7 +35,7 @@ public class GroupPasswordPolicyProviderFactory implements PasswordPolicyProvide
@Override
public PasswordPolicyProvider create(KeycloakSession session) {
return new GroupPasswordPolicyProvider(session.getContext());
return new GroupPasswordPolicyProvider(session);
}
@Override