From f307c013087c6bd61c6a2f015b0abb5d948cfdaf Mon Sep 17 00:00:00 2001 From: Kayathiri Mahendrakumaran Date: Tue, 12 Nov 2024 13:48:49 +0530 Subject: [PATCH 1/2] Honour the sub claim configured in IDP based on config --- ...ProvisioningPostAuthenticationHandler.java | 50 ++++++++++++++-- .../impl/PostAuthAssociationHandler.java | 13 +++++ .../framework/util/FrameworkConstants.java | 2 + .../framework/util/FrameworkUtils.java | 57 ++++++++++++++++++- ...tion.framework.server.feature.default.json | 3 +- .../resources/identity.xml.j2 | 3 +- 6 files changed, 119 insertions(+), 9 deletions(-) diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/JITProvisioningPostAuthenticationHandler.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/JITProvisioningPostAuthenticationHandler.java index 8a9939ea241d..4e439ce7e3b7 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/JITProvisioningPostAuthenticationHandler.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/JITProvisioningPostAuthenticationHandler.java @@ -317,9 +317,23 @@ private PostAuthnHandlerFlowStatus handleRequestFlow(HttpServletRequest request, localClaimValues = new HashMap<>(); } + String externalSubject = stepConfig.getAuthenticatedUser().getAuthenticatedSubjectIdentifier(); + if (FrameworkUtils.isConfiguredIdpSubForFederatedUserAssociationEnabled()) { + String userIdClaimURI = FrameworkUtils.getUserIdClaimURI(stepConfig.getAuthenticatedIdP(), + context.getTenantDomain()); + if (StringUtils.isNotEmpty(userIdClaimURI)) { + externalSubject = stepConfig.getAuthenticatedUser().getUserAttributes().entrySet().stream() + .filter(userAttribute -> userAttribute.getKey().getRemoteClaim().getClaimUri() + .equals(userIdClaimURI)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(null); + } + } + String associatedLocalUser = getLocalUserAssociatedForFederatedIdentifier(stepConfig.getAuthenticatedIdP(), - stepConfig.getAuthenticatedUser().getAuthenticatedSubjectIdentifier(), + externalSubject, context.getTenantDomain()); boolean isUserAllowsToLoginIdp = Boolean.parseBoolean(IdentityUtil .getProperty(ALLOW_LOGIN_TO_IDP)); @@ -356,8 +370,7 @@ private PostAuthnHandlerFlowStatus handleRequestFlow(HttpServletRequest request, FrameworkUtils.getFederatedAssociationManager() .createFederatedAssociation(new User(user), stepConfig.getAuthenticatedIdP(), - stepConfig.getAuthenticatedUser() - .getAuthenticatedSubjectIdentifier()); + externalSubject); associatedLocalUser = user.getDomainQualifiedUsername(); } } catch (UserStoreException e) { @@ -830,8 +843,21 @@ private void callDefaultProvisioningHandler(String username, AuthenticationConte } } - localClaimValues.put(FrameworkConstants.ASSOCIATED_ID, - stepConfig.getAuthenticatedUser().getAuthenticatedSubjectIdentifier()); + String externalSubject = stepConfig.getAuthenticatedUser().getAuthenticatedSubjectIdentifier(); + if (FrameworkUtils.isConfiguredIdpSubForFederatedUserAssociationEnabled()) { + String userIdClaimURI = FrameworkUtils.getUserIdClaimURI(stepConfig.getAuthenticatedIdP(), + context.getTenantDomain()); + if (StringUtils.isNotEmpty(userIdClaimURI)) { + externalSubject = stepConfig.getAuthenticatedUser().getUserAttributes().entrySet().stream() + .filter(userAttribute -> userAttribute.getKey().getRemoteClaim().getClaimUri() + .equals(userIdClaimURI)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(null); + } + } + + localClaimValues.put(FrameworkConstants.ASSOCIATED_ID, externalSubject); localClaimValues.put(FrameworkConstants.IDP_ID, stepConfig.getAuthenticatedIdP()); /* @@ -959,8 +985,20 @@ private void callDefaultProvisioningHandler(String username, AuthenticationConte private void handleConsents(HttpServletRequest request, StepConfig stepConfig, String tenantDomain) throws PostAuthenticationFailedException { + String externalSubject = stepConfig.getAuthenticatedUser().getAuthenticatedSubjectIdentifier(); + if (FrameworkUtils.isConfiguredIdpSubForFederatedUserAssociationEnabled()) { + String userIdClaimURI = FrameworkUtils.getUserIdClaimURI(stepConfig.getAuthenticatedIdP(), tenantDomain); + if (StringUtils.isNotEmpty(userIdClaimURI)) { + externalSubject = stepConfig.getAuthenticatedUser().getUserAttributes().entrySet().stream() + .filter(userAttribute -> userAttribute.getKey().getRemoteClaim().getClaimUri() + .equals(userIdClaimURI)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(null); + } + } String userName = getLocalUserAssociatedForFederatedIdentifier(stepConfig.getAuthenticatedIdP(), - stepConfig.getAuthenticatedUser().getAuthenticatedSubjectIdentifier(), tenantDomain); + externalSubject, tenantDomain); String consent = request.getParameter("consent"); String policyURL = request.getParameter("policy"); if (StringUtils.isNotEmpty(consent)) { diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/PostAuthAssociationHandler.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/PostAuthAssociationHandler.java index ce831f298fd2..1298ab0be1c7 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/PostAuthAssociationHandler.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/PostAuthAssociationHandler.java @@ -200,6 +200,19 @@ private String getUserNameAssociatedWith(AuthenticationContext context, StepConf String associatesUserName; String originalExternalIdpSubjectValueForThisStep = stepConfig.getAuthenticatedUser() .getAuthenticatedSubjectIdentifier(); + if (FrameworkUtils.isConfiguredIdpSubForFederatedUserAssociationEnabled()) { + String userIdClaimURI = FrameworkUtils.getUserIdClaimURI(stepConfig.getAuthenticatedIdP(), + context.getTenantDomain()); + if (StringUtils.isNotEmpty(userIdClaimURI)) { + originalExternalIdpSubjectValueForThisStep = stepConfig.getAuthenticatedUser().getUserAttributes() + .entrySet().stream() + .filter(userAttribute -> userAttribute.getKey().getRemoteClaim().getClaimUri() + .equals(userIdClaimURI)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(null); + } + } try { FrameworkUtils.startTenantFlow(context.getTenantDomain()); FederatedAssociationManager federatedAssociationManager = FrameworkUtils.getFederatedAssociationManager(); diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java index 5532f7bb547e..4422946e8269 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkConstants.java @@ -143,6 +143,8 @@ public abstract class FrameworkConstants { public static final String IDP_RESOURCE_ID = "IDPResourceID"; public static final String ENABLE_JIT_PROVISION_ENHANCE_FEATURE = "JITProvisioning.EnableEnhancedFeature"; public static final String ERROR_CODE_INVALID_ATTRIBUTE_UPDATE = "SUO-10000"; + public static final String ENABLE_CONFIGURED_IDP_SUB_FOR_FEDERATED_USER_ASSOCIATION + = "JITProvisioning.EnableConfiguredIdpSubForFederatedUserAssociation"; // Error details sent from authenticators public static final String AUTH_ERROR_CODE = "AuthErrorCode"; diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java index dab6d72c0fea..648e97b05eee 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java @@ -107,6 +107,7 @@ import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticationResult; import org.wso2.carbon.identity.application.authentication.framework.store.UserSessionStore; import org.wso2.carbon.identity.application.common.model.Claim; +import org.wso2.carbon.identity.application.common.model.ClaimConfig; import org.wso2.carbon.identity.application.common.model.ClaimMapping; import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig; import org.wso2.carbon.identity.application.common.model.IdPGroup; @@ -205,6 +206,7 @@ import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.Config.AUTHENTICATION_CONTEXT_EXPIRY_VALIDATION; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.Config.SKIP_LOCAL_USER_SEARCH_FOR_AUTHENTICATION_FLOW_HANDLERS; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.Config.USER_SESSION_MAPPING_ENABLED; +import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.ENABLE_CONFIGURED_IDP_SUB_FOR_FEDERATED_USER_ASSOCIATION; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.InternalRoleDomains.APPLICATION_DOMAIN; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.InternalRoleDomains.WORKFLOW_DOMAIN; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.REQUEST_PARAM_SP; @@ -256,6 +258,7 @@ public class FrameworkUtils { private static final String OPENJDK_SCRIPTER_CLASS_NAME = "org.openjdk.nashorn.api.scripting.ScriptObjectMirror"; private static final String JDK_SCRIPTER_CLASS_NAME = "jdk.nashorn.api.scripting.ScriptObjectMirror"; private static final String GRAALJS_SCRIPTER_CLASS_NAME = "org.graalvm.polyglot.Context"; + private static final String usernameLocalClaim = "http://wso2.org/claims/username"; private FrameworkUtils() { } @@ -799,6 +802,58 @@ public static Optional getApplicationResourceId(AuthenticationContext co .map(ServiceProvider::getApplicationResourceId); } + /** + * Retrieve the user id claim configured for the federated IDP. + * + * @param federatedIdpName Federated IDP name. + * @param tenantDomain Tenant domain. + * @return User ID claim configured for the IDP. + * @throws PostAuthenticationFailedException PostAuthenticationFailedException. + */ + public static String getUserIdClaimURI(String federatedIdpName, String tenantDomain) + throws PostAuthenticationFailedException { + String userIdClaimURI; + IdentityProvider idp; + try { + idp = FrameworkServiceDataHolder.getInstance().getIdentityProviderManager() + .getIdPByName(federatedIdpName, tenantDomain); + } catch (IdentityProviderManagementException e) { + throw new PostAuthenticationFailedException( + ERROR_WHILE_GETTING_IDP_BY_NAME.getCode(), + String.format(FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_GETTING_IDP_BY_NAME.getMessage(), + tenantDomain), e); + } + if (idp == null) { + return null; + } + ClaimConfig claimConfigs = idp.getClaimConfig(); + if (claimConfigs == null) { + return null; + } + ClaimMapping[] claimMappings = claimConfigs.getClaimMappings(); + if (claimMappings == null || claimMappings.length < 1) { + return null; + } + userIdClaimURI = claimConfigs.getUserClaimURI(); + if (userIdClaimURI != null) { + return userIdClaimURI; + } + ClaimMapping userNameClaimMapping = Arrays.stream(claimMappings).filter(claimMapping -> + StringUtils.equals(usernameLocalClaim, claimMapping.getLocalClaim().getClaimUri())) + .findFirst() + .orElse(null); + if (userNameClaimMapping != null) { + userIdClaimURI = userNameClaimMapping.getRemoteClaim().getClaimUri(); + } + return userIdClaimURI; + } + + + public static boolean isConfiguredIdpSubForFederatedUserAssociationEnabled() { + + return Boolean.parseBoolean(IdentityUtil.getProperty(ENABLE_CONFIGURED_IDP_SUB_FOR_FEDERATED_USER_ASSOCIATION)); + } + private static String getServiceProviderNameByReferer(HttpServletRequest request) { String serviceProviderName = null; @@ -2745,7 +2800,7 @@ public static String getMappedIdpRoleClaimUri(String idpRoleClaimUri, StepConfig } // check for role claim uri in the idaps dialect. for (Entry entry : carbonToStandardClaimMapping.entrySet()) { - if (StringUtils.isNotEmpty(idpRoleMappingURI) && + if (StringUtils.isNotEmpty(idpRoleMappingURI) && idpRoleMappingURI.equalsIgnoreCase(entry.getValue())) { idpRoleMappingURI = entry.getKey(); } diff --git a/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json b/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json index 5a1788816a67..a453c7250a6b 100644 --- a/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json +++ b/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json @@ -263,5 +263,6 @@ "console", "SYSTEM" ], - "authentication.jit_provisioning.associating_to_existing_user": false + "authentication.jit_provisioning.associating_to_existing_user": false, + "authentication.jit_provisioning.enable_configured_idp_sub_for_federated_user_association": false } diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 index 9b3d9becafaf..2c2b69a74762 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 @@ -1122,7 +1122,7 @@ 0 {{oauth.token_generation.retry_count_on_persistence_failures}} - + From 12227dfee3fe23c9fb404a1e2807df587fac3e03 Mon Sep 17 00:00:00 2001 From: Kayathiri Mahendrakumaran Date: Tue, 12 Nov 2024 13:59:04 +0530 Subject: [PATCH 2/2] Fix warnings --- .../authentication/framework/util/FrameworkUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java index 648e97b05eee..539b08179bf3 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/util/FrameworkUtils.java @@ -213,6 +213,7 @@ import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.RequestParams.CORRELATION_ID; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.RequestParams.IS_IDF_INITIATED_FROM_AUTHENTICATOR; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.RequestParams.USER_TENANT_DOMAIN_HINT; +import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.USERNAME_CLAIM; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.USE_IDP_ROLE_CLAIM_AS_IDP_GROUP_CLAIM; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkErrorConstants.ErrorMessages.ERROR_WHILE_GETTING_IDP_BY_NAME; import static org.wso2.carbon.identity.configuration.mgt.core.constant.ConfigurationConstants.ErrorMessages.ERROR_CODE_ATTRIBUTE_DOES_NOT_EXISTS; @@ -258,7 +259,6 @@ public class FrameworkUtils { private static final String OPENJDK_SCRIPTER_CLASS_NAME = "org.openjdk.nashorn.api.scripting.ScriptObjectMirror"; private static final String JDK_SCRIPTER_CLASS_NAME = "jdk.nashorn.api.scripting.ScriptObjectMirror"; private static final String GRAALJS_SCRIPTER_CLASS_NAME = "org.graalvm.polyglot.Context"; - private static final String usernameLocalClaim = "http://wso2.org/claims/username"; private FrameworkUtils() { } @@ -839,7 +839,7 @@ public static String getUserIdClaimURI(String federatedIdpName, String tenantDom return userIdClaimURI; } ClaimMapping userNameClaimMapping = Arrays.stream(claimMappings).filter(claimMapping -> - StringUtils.equals(usernameLocalClaim, claimMapping.getLocalClaim().getClaimUri())) + StringUtils.equals(USERNAME_CLAIM, claimMapping.getLocalClaim().getClaimUri())) .findFirst() .orElse(null); if (userNameClaimMapping != null) {