From 52a92f026ee20e3136fa8c9fb4e1c210ce1aa9f3 Mon Sep 17 00:00:00 2001 From: Pasindu Yeshan Date: Mon, 23 Feb 2026 18:01:49 +0530 Subject: [PATCH 1/5] Fix sub org provisioning tenant domain retrieval --- .../listener/DefaultInboundUserProvisioningListener.java | 8 ++++---- .../provisioning/listener/ProvisioningErrorListener.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/DefaultInboundUserProvisioningListener.java b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/DefaultInboundUserProvisioningListener.java index a3677efc5ce5..4da9f52e0b48 100644 --- a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/DefaultInboundUserProvisioningListener.java +++ b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/DefaultInboundUserProvisioningListener.java @@ -270,12 +270,12 @@ public boolean doPostUpdateUserListOfRole(String roleName, String[] deletedUsers if (threadLocalServiceProvider != null) { serviceProviderIdentifier = threadLocalServiceProvider.getServiceProviderName(); - tenantDomainName = threadLocalServiceProvider.getTenantDomain(); if (threadLocalServiceProvider.getServiceProviderType() == ProvisioningServiceProviderType.OAUTH) { serviceProviderIdentifier = ApplicationManagementService.getInstance() .getServiceProviderNameByClientId( serviceProviderIdentifier, - IdentityApplicationConstants.OAuth2.NAME, tenantDomainName); + IdentityApplicationConstants.OAuth2.NAME, + threadLocalServiceProvider.getTenantDomain()); } } @@ -570,13 +570,13 @@ private boolean provisionEntity(ProvisioningEntity provisioningEntity, String te if (threadLocalServiceProvider != null) { String serviceProvider = threadLocalServiceProvider.getServiceProviderName(); - tenantDomainName = threadLocalServiceProvider.getTenantDomain(); if (threadLocalServiceProvider.getServiceProviderType() == ProvisioningServiceProviderType.OAUTH) { try { serviceProvider = ApplicationManagementService.getInstance() .getServiceProviderNameByClientId( threadLocalServiceProvider.getServiceProviderName(), - IdentityApplicationConstants.OAuth2.NAME, tenantDomainName); + IdentityApplicationConstants.OAuth2.NAME, + threadLocalServiceProvider.getTenantDomain()); } catch (IdentityApplicationManagementException e) { log.error("Error while provisioning", e); return true; diff --git a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/ProvisioningErrorListener.java b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/ProvisioningErrorListener.java index 7a343b0d1781..33d9bc2f852a 100644 --- a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/ProvisioningErrorListener.java +++ b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/listener/ProvisioningErrorListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) + * Copyright (c) 2022-2026, WSO2 Inc. (http://www.wso2.org) * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -296,13 +296,13 @@ private boolean outboundProvisionEntity(ProvisioningEntity provisioningEntity) t if (threadLocalServiceProvider != null) { String serviceProvider = threadLocalServiceProvider.getServiceProviderName(); - tenantDomainName = threadLocalServiceProvider.getTenantDomain(); if (threadLocalServiceProvider.getServiceProviderType() == ProvisioningServiceProviderType.OAUTH) { try { serviceProvider = ApplicationManagementService.getInstance() .getServiceProviderNameByClientId( threadLocalServiceProvider.getServiceProviderName(), - IdentityApplicationConstants.OAuth2.NAME, tenantDomainName); + IdentityApplicationConstants.OAuth2.NAME, + threadLocalServiceProvider.getTenantDomain()); } catch (IdentityApplicationManagementException e) { log.error("Error while provisioning", e); return true; From 4094c5608696cd37477ecdf16ee52350108defb1 Mon Sep 17 00:00:00 2001 From: Pasindu Yeshan Date: Tue, 24 Feb 2026 00:05:42 +0530 Subject: [PATCH 2/5] Implement resident app outbound connector fallback --- .../pom.xml | 6 ++++++ .../OutboundProvisioningManager.java | 19 ++++++++++++++++--- .../provisioning/ProvisioningThread.java | 7 ++++--- .../provisioning/ProvisioningUtil.java | 12 ++++++++++++ 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml b/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml index 83963052fd0f..6f96368af5ca 100644 --- a/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml +++ b/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml @@ -92,6 +92,10 @@ org.wso2.carbon.identity.framework org.wso2.carbon.identity.application.authentication.framework + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.central.log.mgt + org.testng testng @@ -173,6 +177,8 @@ version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.application.authentication.framework.util; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.central.log.mgt.utils; + version="${carbon.identity.package.import.version.range}", !org.wso2.carbon.identity.provisioning.internal, diff --git a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/OutboundProvisioningManager.java b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/OutboundProvisioningManager.java index d274d3ad5719..ee94c44af04b 100644 --- a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/OutboundProvisioningManager.java +++ b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/OutboundProvisioningManager.java @@ -357,9 +357,7 @@ public void provision(ProvisioningEntity provisioningEntity, String serviceProvi } // Any provisioning request coming via Console, considered as coming from the resident SP. - // If the application based outbound provisioning is disabled, resident SP configuration will be used. - if (StringUtils.equals(CONSOLE_APPLICATION_NAME, serviceProviderIdentifier) || - !isApplicationBasedOutboundProvisioningEnabled()) { + if (StringUtils.equals(CONSOLE_APPLICATION_NAME, serviceProviderIdentifier)) { serviceProviderIdentifier = LOCAL_SP; inboundClaimDialect = IdentityProvisioningConstants.WSO2_CARBON_DIALECT; } @@ -393,6 +391,21 @@ public void provision(ProvisioningEntity provisioningEntity, String serviceProvi Map connectors = getOutboundProvisioningConnectors(serviceProvider, spTenantDomainName); + // When application-based outbound provisioning is disabled and the application has no + // outbound provisioning connectors configured, fall back to LOCAL_SP (resident app) connectors. + if (!isApplicationBasedOutboundProvisioningEnabled() && MapUtils.isEmpty(connectors) + && !LOCAL_SP.equals(serviceProviderIdentifier)) { + ServiceProvider localSP = ApplicationManagementService.getInstance() + .getServiceProvider(LOCAL_SP, spTenantDomainName); + if (localSP != null) { + serviceProvider = localSP; + connectors = getOutboundProvisioningConnectors(localSP, spTenantDomainName); + inboundClaimDialect = IdentityProvisioningConstants.WSO2_CARBON_DIALECT; + // LOCAL_SP uses WSO2_CARBON_DIALECT; spClaimMappings is not needed. + spClaimMappings = null; + } + } + ProvisioningEntity outboundProEntity; ExecutorService executors = null; diff --git a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningThread.java b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningThread.java index c251a2dfdcd2..62aa31cec998 100644 --- a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningThread.java +++ b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningThread.java @@ -18,7 +18,6 @@ package org.wso2.carbon.identity.provisioning; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; @@ -118,8 +117,10 @@ public Boolean call() throws IdentityProvisioningException { } success = true; } catch (Exception e) { - String errMsg = "Fail the Provisioning for Entity " + provisioningEntity.getEntityName() + - " For operation = " + provisioningEntity.getOperation(); + String maskedEntityName = ProvisioningUtil.maskIfRequired(provisioningEntity.getEntityName()); + String errMsg = "Outbound provisioning failed for IDP: " + idPName + ", connector: " + connectorType + + ", entity: " + maskedEntityName + ", entity type: " + provisioningEntity.getEntityType() + + ", operation: " + provisioningEntity.getOperation(); log.warn(errMsg); throw new IdentityProvisioningException(errMsg, e); } finally { diff --git a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningUtil.java b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningUtil.java index ac23f53c1261..77c4bb52f262 100644 --- a/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningUtil.java +++ b/components/provisioning/org.wso2.carbon.identity.provisioning/src/main/java/org/wso2/carbon/identity/provisioning/ProvisioningUtil.java @@ -30,6 +30,7 @@ import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; import org.wso2.carbon.identity.application.mgt.ApplicationConstants; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataHandler; import org.wso2.carbon.identity.core.util.IdentityUtil; @@ -618,4 +619,15 @@ public static boolean isApplicationBasedOutboundProvisioningEnabled() { } return applicationBasedOutboundProvisioningEnabled; } + + /** + * Mask the given value if it is required. + * + * @param value Value to be masked. + * @return Masked/unmasked value. + */ + public static String maskIfRequired(String value) { + + return LoggerUtils.isLogMaskingEnable ? LoggerUtils.getMaskedContent(value) : value; + } } From eced60ba94f615b2d5a1c31e5362aade7c7d2422 Mon Sep 17 00:00:00 2001 From: Pasindu Yeshan Date: Wed, 25 Feb 2026 21:42:46 +0530 Subject: [PATCH 3/5] Update outbound provisioning related scopes --- .../resources/api-resource-collection.xml | 26 ++++++++++++++++++- .../resources/api-resource-collection.xml.j2 | 26 ++++++++++++++++++- .../resources/system-api-resource.xml | 13 ++++++++++ .../resources/system-api-resource.xml.j2 | 13 ++++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml index afcd2c298dc5..9c1e01cac1a6 100644 --- a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml @@ -1,6 +1,6 @@