mirror of
https://github.com/bmlong137/keycloak-group-password-policy.git
synced 2025-09-10 22:21:07 +00:00
initial group required action impl (password expiration)
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Brian Long
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.github.jpicht.keycloak.policy;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.Config.Scope;
|
||||||
|
import org.keycloak.authentication.RequiredActionFactory;
|
||||||
|
import org.keycloak.authentication.RequiredActionProvider;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author brian@inteligr8.com
|
||||||
|
*/
|
||||||
|
@AutoService(RequiredActionFactory.class)
|
||||||
|
public class GroupRequiredActionFactory implements RequiredActionFactory {
|
||||||
|
|
||||||
|
private final Logger logger = Logger.getLogger(GroupRequiredActionFactory.class);
|
||||||
|
|
||||||
|
private static final String ID = "groupRequiredAction";
|
||||||
|
private static final String DISPLAY = "Group Action";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RequiredActionProvider create(KeycloakSession session) {
|
||||||
|
return new GroupRequiredActionProvider(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Scope config) {
|
||||||
|
this.logger.trace("init()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayText() {
|
||||||
|
return DISPLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
this.logger.trace("close()");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Brian Long
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.github.jpicht.keycloak.policy;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.PasswordPolicy;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author brian@inteligr8.com
|
||||||
|
*/
|
||||||
|
public class GroupRequiredActionProvider extends RequiredActionMultiplexer {
|
||||||
|
|
||||||
|
private final Logger logger = Logger.getLogger(RequiredActionMultiplexer.class);
|
||||||
|
private final GroupPasswordPolicyFinder finder = new GroupPasswordPolicyFinder();
|
||||||
|
private final KeycloakSession session;
|
||||||
|
|
||||||
|
public GroupRequiredActionProvider(KeycloakSession session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int findDaysToExpire(RealmModel realm, UserModel user) {
|
||||||
|
List<String> policyStrs = this.finder.findPolicies(realm, user);
|
||||||
|
if (policyStrs == null || policyStrs.isEmpty())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Integer minDaysToExpire = null;
|
||||||
|
|
||||||
|
for (String policyStr : policyStrs) {
|
||||||
|
PasswordPolicy policy = PasswordPolicy.parse(this.session, policyStr);
|
||||||
|
int daysToExpire = policy.getDaysToExpirePassword();
|
||||||
|
if (daysToExpire < 0)
|
||||||
|
// policy does not have an expiration characteristic; so ignoring ...
|
||||||
|
continue;
|
||||||
|
|
||||||
|
this.logger.debugf("found password expiration policy: %d days", daysToExpire);
|
||||||
|
|
||||||
|
if (minDaysToExpire == null) {
|
||||||
|
// days to expire was set
|
||||||
|
minDaysToExpire = daysToExpire;
|
||||||
|
} else {
|
||||||
|
// days to expire was set; we want the most restrictive
|
||||||
|
minDaysToExpire = Math.min(minDaysToExpire, daysToExpire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return minDaysToExpire == null ? -1 : minDaysToExpire;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -47,7 +47,7 @@ abstract class RequiredActionMultiplexer implements RequiredActionProvider {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void evaluateTriggers(RequiredActionContext context) {
|
public void evaluateTriggers(RequiredActionContext context) {
|
||||||
this.logger.tracef("evaluateTriggers({})", context.getUser() != null ? context.getUser().getUsername() : null);
|
this.logger.tracef("evaluateTriggers(%s)", context.getUser() != null ? context.getUser().getUsername() : null);
|
||||||
|
|
||||||
int daysToExpirePassword = this.findDaysToExpire(context.getRealm(), context.getUser());
|
int daysToExpirePassword = this.findDaysToExpire(context.getRealm(), context.getUser());
|
||||||
if (daysToExpirePassword > -1) {
|
if (daysToExpirePassword > -1) {
|
||||||
@@ -73,12 +73,12 @@ abstract class RequiredActionMultiplexer implements RequiredActionProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requiredActionChallenge(RequiredActionContext context) {
|
public void requiredActionChallenge(RequiredActionContext context) {
|
||||||
this.logger.tracef("requiredActionChallenge({})", context.getUser() != null ? context.getUser().getUsername() : null);
|
this.logger.tracef("requiredActionChallenge(%s)", context.getUser() != null ? context.getUser().getUsername() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processAction(RequiredActionContext context) {
|
public void processAction(RequiredActionContext context) {
|
||||||
this.logger.tracef("processAction({})", context.getUser() != null ? context.getUser().getUsername() : null);
|
this.logger.tracef("processAction(%s)", context.getUser() != null ? context.getUser().getUsername() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user