From 979250554bda206a430cf91e81451b2dd63034cf Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Wed, 22 Jan 2025 05:34:09 +0530 Subject: [PATCH 1/5] Allow handle claim mappings with idp group to role assigment resolving --- .../identity/oauth2/util/ClaimsUtil.java | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java index e611d36715..84b4f2a9f6 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java @@ -30,6 +30,7 @@ import org.w3c.dom.Element; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.ClaimConfig; @@ -291,6 +292,25 @@ private static List getRequestedLocalClaims(ClaimMapping[] spClaimMappin return requestedLocalClaims; } + /** + * Handle claims from identity provider based on claim configurations. + * + * @param identityProvider Identity Provider. + * @param attributes Relevant Claims coming from IDP + * @param tenantDomain Tenant Domain. + * @param tokenReqMsgCtx Token request message context. + * @return Mapped local claims. + * @throws IdentityException + * @throws IdentityApplicationManagementException + */ + public static Map handleClaimMapping(IdentityProvider identityProvider, + Map attributes, String tenantDomain, + OAuthTokenReqMessageContext tokenReqMsgCtx) + throws IdentityException, IdentityApplicationManagementException { + + return handleClaimMapping(identityProvider, attributes, tenantDomain, tokenReqMsgCtx, false); + } + /** * Handle claims from identity provider based on claim configurations. * @@ -298,26 +318,38 @@ private static List getRequestedLocalClaims(ClaimMapping[] spClaimMappin * @param attributes Relevant Claims coming from IDP * @param tenantDomain Tenant Domain. * @param tokenReqMsgCtx Token request message context. - * @return mapped local claims. + * @return Mapped local claims. * @throws IdentityException * @throws IdentityApplicationManagementException */ public static Map handleClaimMapping(IdentityProvider identityProvider, - Map attributes, String tenantDomain, OAuthTokenReqMessageContext tokenReqMsgCtx) + Map attributes, String tenantDomain, + OAuthTokenReqMessageContext tokenReqMsgCtx, + boolean resolveIdPGroupAssignments) throws IdentityException, IdentityApplicationManagementException { + List assignedRoles = null; + ServiceProvider serviceProvider = null; + if (resolveIdPGroupAssignments) { + serviceProvider = getServiceProvider(tokenReqMsgCtx); + String applicationId = serviceProvider.getApplicationResourceId(); + assignedRoles = getAssignedRolesFromIdPGroups(identityProvider, attributes, applicationId, + tenantDomain); + } boolean proxyUserAttributes = !OAuthServerConfiguration.getInstance() .isConvertOriginalClaimsFromAssertionsToOIDCDialect(); if (proxyUserAttributes) { setHasNonOIDCClaimsProperty(tokenReqMsgCtx); - return attributes; + return appendIdPMappedUserRolesAttributes(attributes, assignedRoles); } ClaimMapping[] idPClaimMappings = identityProvider.getClaimConfig().getClaimMappings(); Map claimsAfterIdpMapping; Map claimsAfterSPMapping = new HashMap<>(); - ServiceProvider serviceProvider = getServiceProvider(tokenReqMsgCtx); + if (serviceProvider == null) { + serviceProvider = getServiceProvider(tokenReqMsgCtx); + } if (ArrayUtils.isNotEmpty(idPClaimMappings)) { if (log.isDebugEnabled()) { @@ -378,7 +410,30 @@ public static Map handleClaimMapping(IdentityProvider identityPr } } } - return claimsAfterSPMapping; + return appendIdPMappedUserRolesAttributes(claimsAfterSPMapping, assignedRoles); + } + + private static List getAssignedRolesFromIdPGroups(IdentityProvider identityProvider, + Map attributes, String applicationId, + String tenantDomain) { + + String idpGroupClaimURI = FrameworkUtils.getEffectiveIdpGroupClaimUri(identityProvider, tenantDomain); + if (StringUtils.isBlank(idpGroupClaimURI)) { + return new ArrayList<>(); + } + + return FrameworkUtils.getAppAssociatedRolesFromFederatedUserAttributes(attributes, identityProvider, + applicationId, idpGroupClaimURI, tenantDomain); + } + + private static Map appendIdPMappedUserRolesAttributes(Map attributes, + List assignedRoles) { + + if (CollectionUtils.isNotEmpty(assignedRoles)) { + attributes.put(FrameworkConstants.IDP_MAPPED_USER_ROLES, + String.join(FrameworkUtils.getMultiAttributeSeparator(), assignedRoles)); + } + return attributes; } /** From da35c4c2ade98f170f8afcd3855a773adee1c9db Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Thu, 23 Jan 2025 13:29:12 +0530 Subject: [PATCH 2/5] Exclude identityProviderMappedUserRoles claim when returning user claims --- .../openidconnect/DefaultOIDCClaimsCallbackHandler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultOIDCClaimsCallbackHandler.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultOIDCClaimsCallbackHandler.java index 28ecc6a82e..21624bcc0c 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultOIDCClaimsCallbackHandler.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/openidconnect/DefaultOIDCClaimsCallbackHandler.java @@ -28,6 +28,7 @@ import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; +import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.ClaimMapping; @@ -172,6 +173,8 @@ private Map getUserClaimsInOIDCDialect(OAuthTokenReqMessageConte // Get claim map from the cached attributes userClaimsInOIDCDialect = getOIDCClaimsFromUserAttributes(userAttributes, requestMsgCtx); } + // Remove the identityProviderMappedUserRoles claim since it is not an OIDC claim. + userClaimsInOIDCDialect.remove(FrameworkConstants.IDP_MAPPED_USER_ROLES); Object hasNonOIDCClaimsProperty = requestMsgCtx.getProperty(OIDCConstants.HAS_NON_OIDC_CLAIMS); if (isPreserverClaimUrisInAssertion(requestMsgCtx) || (hasNonOIDCClaimsProperty != null From d7194b3526f0096f92d2387ffa43397e926f0816 Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Sun, 26 Jan 2025 06:14:26 +0530 Subject: [PATCH 3/5] Bump framework version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 98a2fa4e96..264e862478 100644 --- a/pom.xml +++ b/pom.xml @@ -944,7 +944,7 @@ [1.0.1, 2.0.0) - 7.7.49 + 7.7.140 [5.25.234, 8.0.0) [2.0.0, 3.0.0) From d7dd463d165b1ddb4c4b733acdbfc6dbe0d8c112 Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Sun, 26 Jan 2025 06:34:51 +0530 Subject: [PATCH 4/5] Refactor code --- .../identity/oauth2/util/ClaimsUtil.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java index 84b4f2a9f6..23a84d7c85 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java @@ -19,6 +19,7 @@ package org.wso2.carbon.identity.oauth2.util; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; @@ -29,6 +30,7 @@ import org.opensaml.saml.saml2.core.AttributeStatement; import org.w3c.dom.Element; import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException; import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils; @@ -329,11 +331,9 @@ public static Map handleClaimMapping(IdentityProvider identityPr throws IdentityException, IdentityApplicationManagementException { List assignedRoles = null; - ServiceProvider serviceProvider = null; + ServiceProvider serviceProvider = getServiceProvider(tokenReqMsgCtx); if (resolveIdPGroupAssignments) { - serviceProvider = getServiceProvider(tokenReqMsgCtx); - String applicationId = serviceProvider.getApplicationResourceId(); - assignedRoles = getAssignedRolesFromIdPGroups(identityProvider, attributes, applicationId, + assignedRoles = getAssignedRolesFromIdPGroups(identityProvider, attributes, serviceProvider, tenantDomain); } boolean proxyUserAttributes = !OAuthServerConfiguration.getInstance() @@ -347,9 +347,6 @@ public static Map handleClaimMapping(IdentityProvider identityPr ClaimMapping[] idPClaimMappings = identityProvider.getClaimConfig().getClaimMappings(); Map claimsAfterIdpMapping; Map claimsAfterSPMapping = new HashMap<>(); - if (serviceProvider == null) { - serviceProvider = getServiceProvider(tokenReqMsgCtx); - } if (ArrayUtils.isNotEmpty(idPClaimMappings)) { if (log.isDebugEnabled()) { @@ -414,8 +411,14 @@ public static Map handleClaimMapping(IdentityProvider identityPr } private static List getAssignedRolesFromIdPGroups(IdentityProvider identityProvider, - Map attributes, String applicationId, - String tenantDomain) { + Map attributes, + ServiceProvider serviceProvider, + String tenantDomain) throws FrameworkException { + + if (serviceProvider == null || MapUtils.isEmpty(attributes)) { + return new ArrayList<>(); + } + String applicationId = serviceProvider.getApplicationResourceId(); String idpGroupClaimURI = FrameworkUtils.getEffectiveIdpGroupClaimUri(identityProvider, tenantDomain); if (StringUtils.isBlank(idpGroupClaimURI)) { From cbe31dbad53ee34546a245196081b962fd31d95c Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Sun, 26 Jan 2025 06:42:58 +0530 Subject: [PATCH 5/5] Deprecate previous method and fix comments --- .../identity/oauth2/util/ClaimsUtil.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java index 23a84d7c85..3f2a78bfc2 100644 --- a/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java +++ b/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/util/ClaimsUtil.java @@ -298,13 +298,15 @@ private static List getRequestedLocalClaims(ClaimMapping[] spClaimMappin * Handle claims from identity provider based on claim configurations. * * @param identityProvider Identity Provider. - * @param attributes Relevant Claims coming from IDP - * @param tenantDomain Tenant Domain. - * @param tokenReqMsgCtx Token request message context. + * @param attributes Relevant Claims coming from IDP + * @param tenantDomain Tenant Domain. + * @param tokenReqMsgCtx Token request message context. * @return Mapped local claims. - * @throws IdentityException - * @throws IdentityApplicationManagementException + * @throws IdentityException If an error occurred while handling claim mappings. + * @throws IdentityApplicationManagementException If an error occurred while getting service provider. + * @deprecated Use {@link #handleClaimMapping(IdentityProvider, Map, String, OAuthTokenReqMessageContext, boolean)}. */ + @Deprecated public static Map handleClaimMapping(IdentityProvider identityProvider, Map attributes, String tenantDomain, OAuthTokenReqMessageContext tokenReqMsgCtx) @@ -316,13 +318,14 @@ public static Map handleClaimMapping(IdentityProvider identityPr /** * Handle claims from identity provider based on claim configurations. * - * @param identityProvider Identity Provider - * @param attributes Relevant Claims coming from IDP - * @param tenantDomain Tenant Domain. - * @param tokenReqMsgCtx Token request message context. + * @param identityProvider Identity Provider + * @param attributes Relevant Claims coming from IDP + * @param tenantDomain Tenant Domain. + * @param tokenReqMsgCtx Token request message context. + * @param resolveIdPGroupAssignments Whether resolving IdP Group assignments needed. * @return Mapped local claims. - * @throws IdentityException - * @throws IdentityApplicationManagementException + * @throws IdentityException If an error occurred while handling claim mappings. + * @throws IdentityApplicationManagementException If an error occurred while getting service provider. */ public static Map handleClaimMapping(IdentityProvider identityProvider, Map attributes, String tenantDomain,