Skip to content

Commit

Permalink
Merge pull request #166 from sadilchamishka/fix-saml-response-decrypt…
Browse files Browse the repository at this point in the history
…ion-at-org-level

Use root tenant certificate for signing and verifying SAML request/response assertions
  • Loading branch information
sadilchamishka authored Nov 17, 2023
2 parents 232f829 + 845b602 commit 4667cf7
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~ Copyright (c) 2015-2023, WSO2 LLC. (http://www.wso2.com).
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the 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 "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

Expand Down Expand Up @@ -88,7 +90,6 @@
<dependency>
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wso2.orbit.org.opensaml</groupId>
Expand Down Expand Up @@ -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
</Import-Package>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;

/**
Expand All @@ -29,6 +31,7 @@ public class SAMLSSOAuthenticatorServiceDataHolder {

private RealmService realmService;
private ServerConfigurationService serverConfigurationService;
private OrganizationManager organizationManager;

public static SAMLSSOAuthenticatorServiceDataHolder getInstance() {

Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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));
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down
11 changes: 6 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~ Copyright (c) 2015-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
Expand Down Expand Up @@ -98,7 +98,6 @@
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
<version>${identity.organization.management.core.version}</version>
<scope>test</scope>
</dependency>

<!--SAML Common Util dependency-->
Expand Down Expand Up @@ -286,7 +285,7 @@
<identity.outbound.auth.samlsso.imp.pkg.version.range>[1.0.0, 2.0.0)</identity.outbound.auth.samlsso.imp.pkg.version.range>

<!--Carbon Kernel Version-->
<carbon.kernel.version>4.9.10</carbon.kernel.version>
<carbon.kernel.version>4.9.17</carbon.kernel.version>
<carbon.kernel.feature.version>4.9.0</carbon.kernel.feature.version>
<carbon.kernel.imp.pkg.version.range>[4.4.0, 5.0.0)</carbon.kernel.imp.pkg.version.range>
<carbon.user.api.imp.pkg.version.range>[1.0.1, 2.0.0)</carbon.user.api.imp.pkg.version.range>
Expand All @@ -295,7 +294,9 @@
<carbon.identity.framework.version>5.25.260</carbon.identity.framework.version>
<carbon.identity.framework.imp.pkg.version.range>[5.15.0, 7.0.0)</carbon.identity.framework.imp.pkg.version.range>

<identity.organization.management.core.version>1.0.50</identity.organization.management.core.version>
<identity.organization.management.core.version>1.0.85</identity.organization.management.core.version>
<org.wso2.identity.organization.mgt.core.imp.pkg.version.range>[1.0.0,2.0.0)
</org.wso2.identity.organization.mgt.core.imp.pkg.version.range>

<!--SAML Common Util Version-->
<saml.common.util.version>1.0.3</saml.common.util.version>
Expand Down

0 comments on commit 4667cf7

Please sign in to comment.