Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce method to return given user's password expiry time. #856

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class PasswordPolicyConstants {
public static final String AUTHENTICATION_STATUS = "authenticationStatus";
public static final String BASIC_AUTHENTICATOR = "BasicAuthenticator";
public static final String FALSE = "false";
public static final String TRUE = "true";
public static final String CONFIRMATION_QUERY_PARAM = "&confirmation=";
public static final String PASSWORD_EXPIRED_QUERY_PARAMS = "&passwordExpired=true";
public static final String PASSWORD_EXPIRY_RULES_PREFIX = "passwordExpiry.rule";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@

import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -159,6 +160,8 @@ public static boolean isPasswordExpired(String tenantDomain, String tenantAwareU
throws PostAuthenticationFailedException {

try {
if (!isPasswordExpiryEnabled(tenantDomain)) return false;

UserRealm userRealm = getUserRealm(tenantDomain);
UserStoreManager userStoreManager = getUserStoreManager(userRealm);
String userId = ((AbstractUserStoreManager) userStoreManager).getUserIDFromUserName(tenantAwareUsername);
Expand Down Expand Up @@ -193,7 +196,7 @@ public static boolean isPasswordExpired(String tenantDomain, String tenantAwareU
}
int expiryDays =
rule.getExpiryDays() > 0 ? rule.getExpiryDays() : getPasswordExpiryInDays(tenantDomain);
return daysDifference >= expiryDays || lastPasswordUpdatedTime == null;
return daysDifference >= expiryDays || StringUtils.isBlank(lastPasswordUpdatedTime);
}
}
// Apply default password expiry policy if no specific rule applies.
Expand Down Expand Up @@ -292,7 +295,95 @@ private static boolean isPasswordExpiredUnderDefaultPolicy(String tenantDomain,
throws PostAuthenticationFailedException {

if (skipIfNoApplicableRules) return false;
return lastPasswordUpdatedTime == null || daysDifference >= getPasswordExpiryInDays(tenantDomain);
return StringUtils.isBlank(lastPasswordUpdatedTime) || daysDifference >= getPasswordExpiryInDays(tenantDomain);
}

/**
* This method returns password expiry time for the given user.
*
* @param tenantDomain The tenant domain.
* @param tenantAwareUsername The tenant aware username.
* @param groupIds The group IDs of the user.
* @param roleIds The role IDs of the user.
* @return The password expiry time in milliseconds.
* @throws PostAuthenticationFailedException If an error occurred while getting the password expiry time.
*/
public static Long getUserPasswordExpiryTime(String tenantDomain, String tenantAwareUsername,
List<String> groupIds, List<String> roleIds)
throws PostAuthenticationFailedException {

try {
// If the password expiry is not enabled, password expiry time is not applicable.
if (!isPasswordExpiryEnabled(tenantDomain)) return null;

UserRealm userRealm = getUserRealm(tenantDomain);
UserStoreManager userStoreManager = getUserStoreManager(userRealm);
String userId = ((AbstractUserStoreManager) userStoreManager).getUserIDFromUserName(tenantAwareUsername);
String lastPasswordUpdatedTime =
getLastPasswordUpdatedTime(tenantAwareUsername, userStoreManager, userRealm);

// If last password update time is not available, it will be considered as expired.
if (StringUtils.isBlank(lastPasswordUpdatedTime)) {
return System.currentTimeMillis();
}

long lastPasswordUpdatedTimeInMillis = getLastPasswordUpdatedTimeInMillis(lastPasswordUpdatedTime);
int defaultPasswordExpiryInDays = getPasswordExpiryInDays(tenantDomain);
boolean skipIfNoApplicableRules = isSkipIfNoApplicableRulesEnabled(tenantDomain);

List<PasswordExpiryRule> passwordExpiryRules = getPasswordExpiryRules(tenantDomain);

// If no rules are defined, use the default expiry time if "skipIfNoApplicableRules" is disabled.
if (CollectionUtils.isEmpty(passwordExpiryRules)) {
if (skipIfNoApplicableRules) return null;
return lastPasswordUpdatedTimeInMillis + getDaysTimeInMillis(defaultPasswordExpiryInDays);
}

// If the default behavior is to skip the password expiry, rules with skip logic are not necessary.
List<PasswordExpiryRule> filteredRules = passwordExpiryRules.stream()
.filter(rule -> !skipIfNoApplicableRules ||
!PasswordExpiryRuleOperatorEnum.NE.equals(rule.getOperator()))
.collect(Collectors.toList());

Map<PasswordExpiryRuleAttributeEnum, Set<String>> userAttributes =
new EnumMap<>(PasswordExpiryRuleAttributeEnum.class);
if (groupIds != null) {
userAttributes.put(PasswordExpiryRuleAttributeEnum.GROUPS, new HashSet<>(groupIds));
}
if (roleIds != null) {
userAttributes.put(PasswordExpiryRuleAttributeEnum.ROLES, new HashSet<>(roleIds));
}

for (PasswordExpiryRule rule : filteredRules) {
if (isRuleApplicable(rule, userAttributes, tenantDomain, userId, userStoreManager)) {
// Skip the rule if the operator is not equals.
if (PasswordExpiryRuleOperatorEnum.NE.equals(rule.getOperator())) {
return null;
}
int expiryDays =
rule.getExpiryDays() > 0 ? rule.getExpiryDays() : getPasswordExpiryInDays(tenantDomain);
return lastPasswordUpdatedTimeInMillis + getDaysTimeInMillis(expiryDays);
}
}

if (skipIfNoApplicableRules) return null;
return lastPasswordUpdatedTimeInMillis + getDaysTimeInMillis(defaultPasswordExpiryInDays);
} catch (UserStoreException e) {
throw new PostAuthenticationFailedException(PasswordPolicyConstants.ErrorMessages.
ERROR_WHILE_GETTING_USER_STORE_DOMAIN.getCode(),
PasswordPolicyConstants.ErrorMessages.ERROR_WHILE_GETTING_USER_STORE_DOMAIN.getMessage());
}
}

/**
* This method returns the time in milliseconds for the given number of days.
*
* @param days The number of days.
* @return The time in milliseconds.
*/
private static long getDaysTimeInMillis(int days) {

return (long) days * 24 * 60 * 60 * 1000;
}

/**
Expand Down
Loading
Loading