Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use root tenant certificate for signing and verifying SAML request/response assertions #166

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading