diff --git a/components/org.wso2.carbon.identity.application.authenticator.samlsso/pom.xml b/components/org.wso2.carbon.identity.application.authenticator.samlsso/pom.xml index 36b0be0e..b7985a5f 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.samlsso/pom.xml +++ b/components/org.wso2.carbon.identity.application.authenticator.samlsso/pom.xml @@ -1,18 +1,20 @@ @@ -88,7 +90,6 @@ org.wso2.carbon.identity.organization.management.core org.wso2.carbon.identity.organization.management.service - test org.wso2.orbit.org.opensaml @@ -217,6 +218,8 @@ org.wso2.carbon.user.core.service; version="${carbon.kernel.imp.pkg.version.range}", org.wso2.carbon.user.core.tenant; version="${carbon.kernel.imp.pkg.version.range}", org.wso2.carbon.utils; version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.management.service.util; version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.management.service.exception; version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}", org.osgi.service.component.*;version="${imp.package.version.osgi.services}", org.xml.sax diff --git a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceComponent.java b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceComponent.java index 98d5c326..0384ea72 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceComponent.java +++ b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceComponent.java @@ -1,12 +1,12 @@ /* - * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2017-2023, WSO2 LLC. (http://www.wso2.com). * - * WSO2 Inc. licenses this file to you under the Apache License, + * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an @@ -15,6 +15,7 @@ * specific language governing permissions and limitations * under the License. */ + package org.wso2.carbon.identity.application.authenticator.samlsso.internal; import org.apache.commons.logging.Log; @@ -37,6 +38,7 @@ import org.wso2.carbon.identity.application.authenticator.samlsso.logout.request.SAMLLogoutRequestFactory; import org.wso2.carbon.identity.application.authenticator.samlsso.logout.response.SAMLLogoutResponseFactory; import org.wso2.carbon.identity.core.util.IdentityIOStreamUtils; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.CarbonUtils; @@ -146,6 +148,21 @@ protected void unsetServerConfigurationService(ServerConfigurationService server SAMLSSOAuthenticatorServiceDataHolder.getInstance().setServerConfigurationService(null); } + @Reference(name = "identity.organization.management.component", + service = OrganizationManager.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetOrganizationManager") + protected void setOrganizationManager(OrganizationManager organizationManager) { + + SAMLSSOAuthenticatorServiceDataHolder.getInstance().setOrganizationManager(organizationManager); + } + + protected void unsetOrganizationManager(OrganizationManager organizationManager) { + + SAMLSSOAuthenticatorServiceDataHolder.getInstance().setOrganizationManager(null); + } + public static String getPostPage() { return postPage; } diff --git a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceDataHolder.java b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceDataHolder.java index 7741058a..18a66b41 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceDataHolder.java +++ b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/internal/SAMLSSOAuthenticatorServiceDataHolder.java @@ -1,12 +1,12 @@ /* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2017-2023, WSO2 LLC. (http://www.wso2.com). * - * WSO2 Inc. licenses this file to you under the Apache License, + * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an @@ -15,9 +15,11 @@ * specific language governing permissions and limitations * under the License. */ + package org.wso2.carbon.identity.application.authenticator.samlsso.internal; import org.wso2.carbon.base.api.ServerConfigurationService; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; import org.wso2.carbon.user.core.service.RealmService; /** @@ -29,6 +31,7 @@ public class SAMLSSOAuthenticatorServiceDataHolder { private RealmService realmService; private ServerConfigurationService serverConfigurationService; + private OrganizationManager organizationManager; public static SAMLSSOAuthenticatorServiceDataHolder getInstance() { @@ -58,4 +61,14 @@ public ServerConfigurationService getServerConfigurationService() { public void setServerConfigurationService(ServerConfigurationService serverConfigurationService) { this.serverConfigurationService = serverConfigurationService; } + + public OrganizationManager getOrganizationManager() { + + return organizationManager; + } + + public void setOrganizationManager(OrganizationManager organizationManager) { + + this.organizationManager = organizationManager; + } } diff --git a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManager.java b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManager.java index 8e648db9..d3d78885 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManager.java +++ b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/main/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManager.java @@ -1,12 +1,12 @@ /* - * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2014-2023, WSO2 LLC. (http://www.wso2.com). * - * WSO2 Inc. licenses this file to you under the Apache License, + * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an @@ -104,6 +104,8 @@ import org.wso2.carbon.identity.core.ServiceURLBuilder; import org.wso2.carbon.identity.core.URLBuilderException; import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; +import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; import org.wso2.carbon.identity.saml.common.util.SAMLInitializer; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; @@ -252,8 +254,9 @@ public String buildRequest(HttpServletRequest request, boolean isLogout, boolean SSOUtils.addSignatureToHTTPQueryString(httpQueryString, signatureAlgo, new X509CredentialImpl(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, null)); } else { + String tenantDomain = getSigningTenantDomain(context.getTenantDomain()); SSOUtils.addSignatureToHTTPQueryString(httpQueryString, signatureAlgo, - new X509CredentialImpl(context.getTenantDomain(), null)); + new X509CredentialImpl(tenantDomain, null)); } } if (loginPage.indexOf("?") > -1) { @@ -309,8 +312,9 @@ public String buildPostRequest(HttpServletRequest request, boolean isLogout, if (!isLogout) { requestMessage = buildAuthnRequest(request, isPassive, loginPage, context); if (SSOUtils.isAuthnRequestSigned(properties)) { + String tenantDomain = getSigningTenantDomain(context.getTenantDomain()); SSOUtils.setSignature(requestMessage, signatureAlgo, digestAlgo, includeCert, - new X509CredentialImpl(context.getTenantDomain(), null)); + new X509CredentialImpl(tenantDomain, null)); } } else { String username = (String) request.getSession().getAttribute(SSOConstants.LOGOUT_USERNAME); @@ -322,8 +326,9 @@ public String buildPostRequest(HttpServletRequest request, boolean isLogout, requestMessage = buildLogoutRequest(username, sessionIndex, loginPage, nameQualifier, spNameQualifier, nameIdFormat, context); if (SSOUtils.isLogoutRequestSigned(properties)) { + String tenantDomain = getSigningTenantDomain(context.getTenantDomain()); SSOUtils.setSignature(requestMessage, signatureAlgo, digestAlgo, includeCert, - new X509CredentialImpl(context.getTenantDomain(), null)); + new X509CredentialImpl(tenantDomain, null)); } } @@ -1294,6 +1299,7 @@ protected void validateAssertionValidityPeriod(Assertion assertion) throws SAMLS */ protected Assertion getDecryptedAssertion(EncryptedAssertion encryptedAssertion) throws Exception { + String tenantDomain = getSigningTenantDomain(this.tenantDomain); X509Credential credential = new X509CredentialImpl(tenantDomain, null); KeyInfoCredentialResolver keyResolver = new StaticKeyInfoCredentialResolver(credential); EncryptedKey key = getEncryptedKey(encryptedAssertion); @@ -1374,4 +1380,35 @@ private EncryptedKey getEncryptedKey(EncryptedAssertion encryptedAssertion) thro } throw new Exception("Could not obtain the encrypted key from the encrypted assertion."); } + + /** + * Resolve the tenant domain which is used to sign the request/response. + * + * @param tenantDomain The tenant domain from the context. + * @return The tenant domain which is used to sign the request/response. + */ + private String getSigningTenantDomain(String tenantDomain) { + + boolean isOrganization; + try { + isOrganization = OrganizationManagementUtil.isOrganization(tenantDomain); + } catch (OrganizationManagementException e) { + log.error("Error while checking the tenant domain is related to an organization", e); + return tenantDomain; + } + if (!isOrganization) { + return tenantDomain; + } + try { + String organizationId = SAMLSSOAuthenticatorServiceDataHolder.getInstance().getOrganizationManager() + .resolveOrganizationId(tenantDomain); + String rootOrganizationId = SAMLSSOAuthenticatorServiceDataHolder.getInstance().getOrganizationManager() + .getPrimaryOrganizationId(organizationId); + return SAMLSSOAuthenticatorServiceDataHolder.getInstance().getOrganizationManager() + .resolveTenantDomain(rootOrganizationId); + } catch (OrganizationManagementException e) { + log.error("Error while resolving tenant domain for organization id: ", e); + return tenantDomain; + } + } } diff --git a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/test/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManagerTest.java b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/test/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManagerTest.java index 38cecc97..d9df128b 100644 --- a/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/test/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManagerTest.java +++ b/components/org.wso2.carbon.identity.application.authenticator.samlsso/src/test/java/org/wso2/carbon/identity/application/authenticator/samlsso/manager/DefaultSAML2SSOManagerTest.java @@ -51,6 +51,7 @@ import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; import org.wso2.carbon.identity.core.ServiceURLBuilder; import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.tenant.TenantManager; @@ -70,6 +71,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPathFactory; +import static org.mockito.ArgumentMatchers.anyString; import static org.powermock.api.mockito.PowerMockito.doNothing; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @@ -125,7 +127,7 @@ @PowerMockIgnore({"javax.xml.datatype.*","org.mockito.*","org.powermock.api.mockito.invocation.*","javax.crypto.Cipher"}) @PrepareForTest({FileBasedConfigurationBuilder.class, IdentityUtil.class, DocumentBuilderFactory.class, KeyStoreManager.class, DOMImplementationRegistry.class, XPathFactory.class, FrameworkUtils.class, - ServiceURLBuilder.class}) + ServiceURLBuilder.class, OrganizationManagementUtil.class}) public class DefaultSAML2SSOManagerTest { @Mock @@ -512,6 +514,8 @@ public Object[][] postRequestBuilderData() { public void buildPostRequest(boolean isLogout, String tenantDomain, Object inboundRequestData, Object outboundRequestData) throws Exception { + mockStatic(OrganizationManagementUtil.class); + when(OrganizationManagementUtil.isOrganization(anyString())).thenReturn(false); mockStatic(FrameworkUtils.class); doNothing().when(FrameworkUtils.class, TestConstants.END_TENANT_FLOW); diff --git a/pom.xml b/pom.xml index 8cad7293..83e802d6 100644 --- a/pom.xml +++ b/pom.xml @@ -1,8 +1,8 @@ @@ -286,7 +285,7 @@ [1.0.0, 2.0.0) - 4.9.10 + 4.9.17 4.9.0 [4.4.0, 5.0.0) [1.0.1, 2.0.0) @@ -295,7 +294,9 @@ 5.25.260 [5.15.0, 7.0.0) - 1.0.50 + 1.0.85 + [1.0.0,2.0.0) + 1.0.3