From dab73e12b9ba1e14b5e97a8b418985c382751698 Mon Sep 17 00:00:00 2001 From: mpmadhavig Date: Wed, 11 Oct 2023 15:42:27 +0530 Subject: [PATCH 1/3] Resolve users according to userstore preference order if configured. --- .../login/resolver/regex/RegexResolver.java | 126 +++++++++++++++++- 1 file changed, 123 insertions(+), 3 deletions(-) diff --git a/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java b/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java index 0653183922..0cf61ba9c6 100644 --- a/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java +++ b/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java @@ -28,12 +28,20 @@ import org.wso2.carbon.user.api.ClaimManager; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.UniqueIDUserStoreManager; +import org.wso2.carbon.user.core.UserCoreConstants; import org.wso2.carbon.user.core.UserRealm; +import org.wso2.carbon.user.core.UserStoreManager; +import org.wso2.carbon.user.core.common.AbstractUserStoreManager; import org.wso2.carbon.user.core.common.AuthenticationResult; +import org.wso2.carbon.user.core.common.IterativeUserStoreManager; import org.wso2.carbon.user.core.common.User; +import org.wso2.carbon.user.core.config.UserStorePreferenceOrderSupplier; import org.wso2.carbon.user.core.constants.UserCoreClaimConstants; +import org.wso2.carbon.user.core.model.UserMgtContext; import org.wso2.carbon.user.core.util.UserCoreUtil; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -79,6 +87,7 @@ private void resolveDistinctUsersForClaims(String loginAttribute, List a Set uniqueUserIds = new HashSet<>(); Map> distinctUsers = new HashMap<>(); + List userStorePreferenceOrder = getUserStorePreferenceOrder(); // Resolve the user from the regex matching. for (String claimURI : allowedAttributes) { @@ -91,7 +100,8 @@ private void resolveDistinctUsersForClaims(String loginAttribute, List a String domainSeparateAttribute = UserCoreUtil.removeDomainFromName(loginAttribute); if (pattern.matcher(domainSeparateAttribute).matches()) { - List userList = userStoreManager.getUserListWithID(claimURI, loginAttribute, null); + List userList = getUserList(claimURI, loginAttribute, userStorePreferenceOrder, userStoreManager); + if (userList.isEmpty()) { continue; } @@ -132,8 +142,8 @@ private void resolveDistinctUsersForClaims(String loginAttribute, List a Claim usernameClaim = claimManager.getClaim(UserCoreClaimConstants.USERNAME_CLAIM_URI); if (allowedAttributes.contains(UserCoreClaimConstants.USERNAME_CLAIM_URI) && StringUtils.isBlank(usernameClaim.getRegEx())) { - List userList = userStoreManager.getUserListWithID(UserCoreClaimConstants.USERNAME_CLAIM_URI, - loginAttribute, null); + List userList = getUserList(UserCoreClaimConstants.USERNAME_CLAIM_URI, loginAttribute, + userStorePreferenceOrder, userStoreManager); if (!userList.isEmpty()) { List allowedDistinctUsersForClaim = userList.stream() .filter(user -> uniqueUserIds.add(user.getUserID())) @@ -158,6 +168,116 @@ private void resolveDistinctUsersForClaims(String loginAttribute, List a } } + /** + * This method is used to get the user list according to the user store preference order if configured. + * If the login attribute contains a domain name, resolve users from the corresponding user store. + * + * @param claimURI Claim URI. + * @param loginAttribute Login attribute. + * @param userStorePreferenceOrder User store preference order. + * @param userStoreManager User store manager. + * @return User list. + * @throws org.wso2.carbon.user.core.UserStoreException If an error occurred while getting the user list. + */ + private List getUserList(String claimURI, String loginAttribute, List userStorePreferenceOrder, + UniqueIDUserStoreManager userStoreManager) + throws org.wso2.carbon.user.core.UserStoreException { + + if (!loginAttribute.contains(UserCoreConstants.DOMAIN_SEPARATOR) && userStorePreferenceOrder != null + && !userStorePreferenceOrder.isEmpty()) { + IterativeUserStoreManager iterativeUserStoreManager = generateUserStoreChain(userStorePreferenceOrder, + (AbstractUserStoreManager) userStoreManager); + if (iterativeUserStoreManager != null) { + return getUserListAccordingToUserStorePreferenceOrder(claimURI, loginAttribute, + iterativeUserStoreManager); + } + } + return userStoreManager.getUserListWithID(claimURI, loginAttribute, null); + } + + /** + * This method is used to get the user list according to the user store preference order. + * + * @param claimURI Claim URI. + * @param loginAttribute Login attribute. + * @param userStoreManager User store manager. + * @return User list. + * @throws org.wso2.carbon.user.core.UserStoreException If an error occurred while getting the user list. + */ + private List getUserListAccordingToUserStorePreferenceOrder(String claimURI, String loginAttribute, + IterativeUserStoreManager userStoreManager) + throws org.wso2.carbon.user.core.UserStoreException { + + List userList = new ArrayList<>(); + IterativeUserStoreManager currentUserStoreManager = userStoreManager; + while (currentUserStoreManager != null) { + userList.addAll(currentUserStoreManager.getAbstractUserStoreManager().getUserListWithID(claimURI, + loginAttribute, null)); + currentUserStoreManager = currentUserStoreManager.nextUserStoreManager(); + } + + return userList; + } + + /** + * This method is used to get the user store preference order. + * + * @return User store preference order. + * @throws org.wso2.carbon.user.core.UserStoreException If an error occurred while getting the user store + */ + private List getUserStorePreferenceOrder() throws org.wso2.carbon.user.core.UserStoreException { + + UserMgtContext userMgtContext = UserCoreUtil.getUserMgtContextFromThreadLocal(); + if (userMgtContext != null) { + UserStorePreferenceOrderSupplier> + userStorePreferenceSupplier = userMgtContext.getUserStorePreferenceOrderSupplier(); + if (userStorePreferenceSupplier != null) { + List userStorePreferenceOrder = userStorePreferenceSupplier.get(); + if (userStorePreferenceOrder != null) { + return userStorePreferenceOrder; + } + } + } + + return Collections.emptyList(); + } + + /** + * This method is used to generate a user store chain using the user store preference order. + * + * @param userStorePreferenceOrder User store preference order. + * @param abstractUserStoreManager Abstract user store manager. + * @return IterativeUserStoreManager. + * @throws org.wso2.carbon.user.core.UserStoreException If an error occurred while generating the user store chain. + */ + private IterativeUserStoreManager generateUserStoreChain(List userStorePreferenceOrder, + AbstractUserStoreManager abstractUserStoreManager) + throws org.wso2.carbon.user.core.UserStoreException { + + IterativeUserStoreManager initialUserStoreManager = null; + IterativeUserStoreManager prevUserStoreManager = null; + for (String domainName : userStorePreferenceOrder) { + UserStoreManager userStoreManager = abstractUserStoreManager.getSecondaryUserStoreManager(domainName); + // If the user store manager is instance of AbstractUserStoreManager then generate a user store chain using + // IterativeUserStoreManager. + if (userStoreManager instanceof AbstractUserStoreManager) { + if (initialUserStoreManager == null) { + prevUserStoreManager = new IterativeUserStoreManager((AbstractUserStoreManager) userStoreManager); + initialUserStoreManager = prevUserStoreManager; + } else { + IterativeUserStoreManager currentUserStoreManager = new IterativeUserStoreManager( + (AbstractUserStoreManager) userStoreManager); + prevUserStoreManager.setNextUserStoreManager(currentUserStoreManager); + prevUserStoreManager = currentUserStoreManager; + } + } else { + return null; + } + } + // Authenticate using the initial user store from the user store preference list. + return initialUserStoreManager; + } + private void setResolvedUserResult(List userList, String claimURI, String loginAttribute, ResolvedUserResult resolvedUserResult, Claim claim) throws org.wso2.carbon.user.core.UserStoreException { From 43c2ecb8a4a02e00026472a7be2cb4b72de8d99c Mon Sep 17 00:00:00 2001 From: mpmadhavig Date: Wed, 11 Oct 2023 22:33:55 +0530 Subject: [PATCH 2/3] Update generateUserStoreChain method variable naming. --- .../login/resolver/regex/RegexResolver.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java b/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java index 0cf61ba9c6..2beb999a14 100644 --- a/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java +++ b/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java @@ -255,20 +255,21 @@ private IterativeUserStoreManager generateUserStoreChain(List userStoreP throws org.wso2.carbon.user.core.UserStoreException { IterativeUserStoreManager initialUserStoreManager = null; - IterativeUserStoreManager prevUserStoreManager = null; + IterativeUserStoreManager currentUserStoreManager = null; for (String domainName : userStorePreferenceOrder) { UserStoreManager userStoreManager = abstractUserStoreManager.getSecondaryUserStoreManager(domainName); // If the user store manager is instance of AbstractUserStoreManager then generate a user store chain using // IterativeUserStoreManager. if (userStoreManager instanceof AbstractUserStoreManager) { if (initialUserStoreManager == null) { - prevUserStoreManager = new IterativeUserStoreManager((AbstractUserStoreManager) userStoreManager); - initialUserStoreManager = prevUserStoreManager; + currentUserStoreManager = + new IterativeUserStoreManager((AbstractUserStoreManager) userStoreManager); + initialUserStoreManager = currentUserStoreManager; } else { - IterativeUserStoreManager currentUserStoreManager = new IterativeUserStoreManager( + IterativeUserStoreManager nextUserStoreManager = new IterativeUserStoreManager( (AbstractUserStoreManager) userStoreManager); - prevUserStoreManager.setNextUserStoreManager(currentUserStoreManager); - prevUserStoreManager = currentUserStoreManager; + currentUserStoreManager.setNextUserStoreManager(nextUserStoreManager); + currentUserStoreManager = nextUserStoreManager; } } else { return null; From 37a448d1f5b1f38722f87e1db377f029cd4f255a Mon Sep 17 00:00:00 2001 From: mpmadhavig Date: Thu, 12 Oct 2023 10:49:35 +0530 Subject: [PATCH 3/3] Extract domain to get the domainAwareUsername. --- .../multi/attribute/login/resolver/regex/RegexResolver.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java b/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java index 2beb999a14..65c9a44b07 100644 --- a/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java +++ b/components/org.wso2.carbon.identity.multi.attribute.login/org.wso2.carbon.identity.multi.attribute.login.resolver.regex/src/main/java/org/wso2/carbon/identity/multi/attribute/login/resolver/regex/RegexResolver.java @@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.identity.multi.attribute.login.mgt.MultiAttributeLoginResolver; import org.wso2.carbon.identity.multi.attribute.login.mgt.ResolvedUserResult; import org.wso2.carbon.identity.multi.attribute.login.resolver.regex.utils.UserResolverUtil; @@ -211,8 +212,10 @@ private List getUserListAccordingToUserStorePreferenceOrder(String claimUR List userList = new ArrayList<>(); IterativeUserStoreManager currentUserStoreManager = userStoreManager; while (currentUserStoreManager != null) { + String domainName = UserCoreUtil.getDomainName(currentUserStoreManager.getRealmConfiguration()); + String domainAwareUsername = domainName + CarbonConstants.DOMAIN_SEPARATOR + loginAttribute; userList.addAll(currentUserStoreManager.getAbstractUserStoreManager().getUserListWithID(claimURI, - loginAttribute, null)); + domainAwareUsername, null)); currentUserStoreManager = currentUserStoreManager.nextUserStoreManager(); }