diff --git a/components/identity-core/org.wso2.carbon.identity.core/pom.xml b/components/identity-core/org.wso2.carbon.identity.core/pom.xml
index baf9f2862eb5..68e4d608a022 100644
--- a/components/identity-core/org.wso2.carbon.identity.core/pom.xml
+++ b/components/identity-core/org.wso2.carbon.identity.core/pom.xml
@@ -142,6 +142,11 @@
xml-apis
xml-apis
+
+ com.h2database
+ h2
+ test
+
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java
index b2b0040a84a4..7e8907e688c7 100644
--- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java
@@ -29,15 +29,16 @@
*/
public class SAMLSSOServiceProviderManager {
- SAMLServiceProviderPersistenceManagerFactory
- samlSSOPersistenceManagerFactory = new SAMLServiceProviderPersistenceManagerFactory();
- SAMLSSOServiceProviderDAO serviceProviderDAO = samlSSOPersistenceManagerFactory.getSAMLServiceProviderPersistenceManager();
+ SAMLServiceProviderPersistenceManagerFactory samlSSOPersistenceManagerFactory =
+ new SAMLServiceProviderPersistenceManagerFactory();
+ SAMLSSOServiceProviderDAO serviceProviderDAO =
+ samlSSOPersistenceManagerFactory.getSAMLServiceProviderPersistenceManager();
/**
* Add a saml service provider.
*
- * @param serviceProviderDO Service provider information object.
- * @param tenantId Tenant ID.
+ * @param serviceProviderDO Service provider information object.
+ * @param tenantId Tenant ID.
* @return True if success.
* @throws IdentityException Error when adding the SAML service provider.
*/
@@ -50,9 +51,9 @@ public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, in
/**
* Update a saml service provider if already exists.
*
- * @param serviceProviderDO Service provider information object.
- * @param currentIssuer Issuer of the service provider before the update.
- * @param tenantId Tenant ID.
+ * @param serviceProviderDO Service provider information object.
+ * @param currentIssuer Issuer of the service provider before the update.
+ * @param tenantId Tenant ID.
* @return True if success.
* @throws IdentityException Error when updating the SAML service provider.
*/
@@ -65,7 +66,7 @@ public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO,
/**
* Get all the saml service providers.
*
- * @param tenantId Tenant ID.
+ * @param tenantId Tenant ID.
* @return Array of SAMLSSOServiceProviderDO.
* @throws IdentityException Error when getting the SAML service providers.
*/
@@ -77,8 +78,8 @@ public SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) throws Ident
/**
* Get SAML issuer properties from service provider by saml issuer name.
*
- * @param issuer SAML issuer name.
- * @param tenantId Tenant ID.
+ * @param issuer SAML issuer name.
+ * @param tenantId Tenant ID.
* @return SAMLSSOServiceProviderDO
* @throws IdentityException Error when getting the SAML service provider.
*/
@@ -90,13 +91,12 @@ public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId)
/**
* Check whether SAML issuer exists by saml issuer name.
*
- * @param issuer SAML issuer name.
- * @param tenantId Tenant ID.
+ * @param issuer SAML issuer name.
+ * @param tenantId Tenant ID.
* @return True if exists
* @throws IdentityException Error when checking the SAML service provider.
*/
- public boolean isServiceProviderExists(String issuer, int tenantId)
- throws IdentityException {
+ public boolean isServiceProviderExists(String issuer, int tenantId) throws IdentityException {
return serviceProviderDAO.isServiceProviderExists(issuer, tenantId);
}
@@ -104,8 +104,8 @@ public boolean isServiceProviderExists(String issuer, int tenantId)
/**
* Removes the SAML configuration related to the application, idenfied by the issuer.
*
- * @param issuer Issuer of the SAML application.
- * @param tenantId Tenant ID.
+ * @param issuer Issuer of the SAML application.
+ * @param tenantId Tenant ID.
* @throws IdentityException Error when removing the SAML configuration.
*/
public boolean removeServiceProvider(String issuer, int tenantId) throws IdentityException {
@@ -116,8 +116,8 @@ public boolean removeServiceProvider(String issuer, int tenantId) throws Identit
/**
* Upload the SAML configuration related to the application, using metadata.
*
- * @param samlssoServiceProviderDO SAML service provider information object.
- * @param tenantId Tenant ID.
+ * @param samlssoServiceProviderDO SAML service provider information object.
+ * @param tenantId Tenant ID.
* @return SAML service provider information object.
* @throws IdentityException Error when uploading the SAML configuration.
*/
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/JDBCSAMLSSOServiceProviderDAOImpl.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/JDBCSAMLSSOServiceProviderDAOImpl.java
new file mode 100644
index 000000000000..b2c8aaf6c234
--- /dev/null
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/JDBCSAMLSSOServiceProviderDAOImpl.java
@@ -0,0 +1,626 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * 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
+ *
+ * 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.
+ */
+
+package org.wso2.carbon.identity.core.dao;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate;
+import org.wso2.carbon.database.utils.jdbc.NamedPreparedStatement;
+import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException;
+import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException;
+import org.wso2.carbon.identity.base.IdentityException;
+import org.wso2.carbon.identity.core.CertificateRetriever;
+import org.wso2.carbon.identity.core.CertificateRetrievingException;
+import org.wso2.carbon.identity.core.DatabaseCertificateRetriever;
+import org.wso2.carbon.identity.core.IdentityRegistryResources;
+import org.wso2.carbon.identity.core.KeyStoreCertificateRetriever;
+import org.wso2.carbon.identity.core.model.ServiceProviderProperty;
+import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO;
+import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
+import org.wso2.carbon.identity.core.util.JdbcUtils;
+import org.wso2.carbon.user.api.Tenant;
+
+import java.security.cert.X509Certificate;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import static org.wso2.carbon.identity.core.util.JdbcUtils.isH2DB;
+
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML_SCHEMA_VERSION;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.CERTIFICATE_PROPERTY_NAME;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ID;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.TENANT_ID;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ISSUER;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.DEFAULT_ASSERTION_CONSUMER_URL;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.NAME_ID_FORMAT;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.CERT_ALIAS;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.REQ_SIG_VALIDATION;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SIGN_RESPONSE;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SIGN_ASSERTIONS;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SIGNING_ALGO;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.DIGEST_ALGO;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ENCRYPT_ASSERTION;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ASSERTION_ENCRYPTION_ALGO;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.KEY_ENCRYPTION_ALGO;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ATTR_PROFILE_ENABLED;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ATTR_SERVICE_INDEX;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_PROFILE_ENABLED;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_METHOD;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_RESPONSE_URL;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_REQUEST_URL;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.IDP_INIT_SSO_ENABLED;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.IDP_INIT_SLO_ENABLED;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.QUERY_REQUEST_PROFILE_ENABLED;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ECP_ENABLED;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ARTIFACT_BINDING_ENABLED;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ARTIFACT_RESOLVE_REQ_SIG_VALIDATION;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.IDP_ENTITY_ID_ALIAS;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ISSUER_QUALIFIER;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.VERSION;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.CREATED_AT;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.UPDATED_AT;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.PROPERTY_NAME;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.PROPERTY_VALUE;
+import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SP_ID;
+
+import static java.time.ZoneOffset.UTC;
+
+/**
+ * Implementation of the SAMLSSOServiceProviderDAO interface for JDBC-based persistence.
+ */
+public class JDBCSAMLSSOServiceProviderDAOImpl implements SAMLSSOServiceProviderDAO {
+
+ private final Calendar CALENDAR = Calendar.getInstance(TimeZone.getTimeZone(UTC));
+ private static final Log LOG = LogFactory.getLog(JDBCSAMLSSOServiceProviderDAOImpl.class);
+
+ public JDBCSAMLSSOServiceProviderDAOImpl() {
+
+ }
+
+ @Override
+ public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws IdentityException {
+
+ validateServiceProvider(serviceProviderDO);
+ try {
+ if (processIsServiceProviderExists(serviceProviderDO.getIssuer(),tenantId)) {
+ debugLog(serviceProviderInfo(serviceProviderDO) + " already exists.");
+ return false;
+ }
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ namedJdbcTemplate.withTransaction(template -> {
+ processAddServiceProvider(serviceProviderDO, tenantId);
+ processAddSPProperties(serviceProviderDO, tenantId);
+ return null;
+ });
+ debugLog(serviceProviderInfo(serviceProviderDO) + " is added successfully.");
+ return true;
+ } catch (TransactionException | DataAccessException e) {
+ String msg = "Error while adding " + serviceProviderInfo(serviceProviderDO);
+ throw new IdentityException(msg, e);
+ }
+ }
+
+ @Override
+ public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, String currentIssuer, int tenantId)
+ throws IdentityException {
+
+ validateServiceProvider(serviceProviderDO);
+ String newIssuer = serviceProviderDO.getIssuer();
+ boolean isIssuerUpdated = !StringUtils.equals(currentIssuer, newIssuer);
+
+ try {
+ if (isIssuerUpdated && processIsServiceProviderExists(newIssuer, tenantId)) {
+ debugLog(serviceProviderInfo(serviceProviderDO) + " already exists.");
+ return false;
+ }
+ int serviceProviderId = processGetServiceProviderId(currentIssuer, tenantId);
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ namedJdbcTemplate.withTransaction(template -> {
+ processUpdateServiceProvider(serviceProviderDO, serviceProviderId, tenantId);
+ processUpdateSPProperties(serviceProviderDO, serviceProviderId);
+ return null;
+ });
+ debugLog(serviceProviderInfo(serviceProviderDO) + " is updated successfully.");
+ return true;
+ } catch (TransactionException | DataAccessException e) {
+ String msg = "Error while updating " + serviceProviderInfo(serviceProviderDO);
+ throw new IdentityException(msg, e);
+ }
+ }
+
+ @Override
+ public SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) throws IdentityException {
+
+ List serviceProvidersList;
+ try {
+ serviceProvidersList = processGetServiceProviders(tenantId);
+ } catch (DataAccessException e) {
+ throw new IdentityException("Error reading Service Providers", e);
+ }
+ return serviceProvidersList.toArray(new SAMLSSOServiceProviderDO[0]);
+ }
+
+ @Override
+ public boolean removeServiceProvider(String issuer, int tenantId) throws IdentityException {
+
+ if (StringUtils.isBlank(issuer)) {
+ throw new IllegalArgumentException("Trying to delete issuer \'" + issuer + "\'");
+ }
+ try {
+ if (!processIsServiceProviderExists(issuer, tenantId)) {
+ debugLog("Service Provider with issuer " + issuer + " does not exist.");
+ return false;
+ }
+ processDeleteServiceProvider(issuer, tenantId);
+ return true;
+ } catch (DataAccessException e) {
+ String msg = "Error removing the service provider with name: " + issuer;
+ throw new IdentityException(msg, e);
+ }
+ }
+
+ @Override
+ public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) throws IdentityException {
+
+ SAMLSSOServiceProviderDO serviceProviderDO = null;
+
+ try {
+ if (isServiceProviderExists(issuer, tenantId)) {
+ serviceProviderDO = processGetServiceProvider(issuer, tenantId);
+ }
+ } catch (DataAccessException e) {
+ throw IdentityException.error(String.format(
+ "An error occurred while retrieving the " + "the service provider with the issuer '%s'", issuer),
+ e);
+ }
+ if (serviceProviderDO == null) {
+ return null;
+ }
+ try {
+ String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId);
+ // Load the certificate stored in the database, if signature validation is enabled.
+ if (serviceProviderDO.isDoValidateSignatureInRequests() ||
+ serviceProviderDO.isDoValidateSignatureInArtifactResolve() ||
+ serviceProviderDO.isDoEnableEncryptedAssertion()) {
+
+ Tenant tenant = IdentityTenantUtil.getTenant(tenantId);
+ serviceProviderDO.setX509Certificate(getApplicationCertificate(serviceProviderDO, tenant));
+ }
+ serviceProviderDO.setTenantDomain(tenantDomain);
+ } catch (DataAccessException | CertificateRetrievingException e) {
+ throw IdentityException.error(String.format("An error occurred while getting the " +
+ "application certificate for validating the requests from the issuer '%s'", issuer), e);
+ }
+ return serviceProviderDO;
+ }
+
+ @Override
+ public boolean isServiceProviderExists(String issuer, int tenantId) throws IdentityException {
+
+ try {
+ return processIsServiceProviderExists(issuer, tenantId);
+ } catch (DataAccessException e) {
+ String msg = "Error while checking existence of Service Provider with issuer: " + issuer;
+ throw new IdentityException(msg, e);
+ }
+ }
+
+ @Override
+ public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId)
+ throws IdentityException {
+
+ validateServiceProvider(serviceProviderDO);
+ if (serviceProviderDO.getDefaultAssertionConsumerUrl() == null) {
+ throw new IdentityException("No default assertion consumer URL provided for service provider :" +
+ serviceProviderDO.getIssuer());
+ }
+
+ try {
+ if (processIsServiceProviderExists(serviceProviderDO.getIssuer(), tenantId)) {
+ debugLog(serviceProviderInfo(serviceProviderDO) + " already exists.");
+ throw new IdentityException(serviceProviderInfo(serviceProviderDO) + " already exists.");
+ }
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ namedJdbcTemplate.withTransaction(template -> {
+ processAddServiceProvider(serviceProviderDO, tenantId);
+ processAddSPProperties(serviceProviderDO, tenantId);
+ return null;
+ });
+ debugLog(serviceProviderInfo(serviceProviderDO) + " is added successfully.");
+ return serviceProviderDO;
+ } catch (TransactionException | DataAccessException e) {
+ String msg = "Error while adding " + serviceProviderInfo(serviceProviderDO);
+ throw new IdentityException(msg, e);
+ }
+ }
+
+ private void debugLog(String message) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(message);
+ }
+ }
+
+ private boolean processIsServiceProviderExists(String issuer, int tenantId) throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ Integer serviceProviderId =
+ namedJdbcTemplate.fetchSingleRecord(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML_SP_ID_BY_ISSUER,
+ (resultSet, rowNumber) -> resultSet.getInt(ID), preparedStatement -> {
+ preparedStatement.setString(ISSUER, issuer);
+ preparedStatement.setInt(TENANT_ID, tenantId);
+ });
+ return serviceProviderId != null;
+ }
+
+ private void validateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws IdentityException {
+
+ if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null ||
+ StringUtils.isBlank(serviceProviderDO.getIssuer())) {
+ throw new IdentityException("Issuer cannot be found in the provided arguments.");
+ }
+
+ if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier()) &&
+ !serviceProviderDO.getIssuer().contains(IdentityRegistryResources.QUALIFIER_ID)) {
+ serviceProviderDO.setIssuer(
+ getIssuerWithQualifier(serviceProviderDO.getIssuer(), serviceProviderDO.getIssuerQualifier()));
+ }
+ }
+
+ private String serviceProviderInfo(SAMLSSOServiceProviderDO serviceProviderDO) {
+
+ if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) {
+ return "SAML2 Service Provider with issuer: " + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) +
+ " and qualifier name " + serviceProviderDO.getIssuerQualifier();
+ } else {
+ return "SAML2 Service Provider with issuer: " + serviceProviderDO.getIssuer();
+ }
+ }
+
+ /**
+ * Get the issuer value to be added to registry by appending the qualifier.
+ *
+ * @param issuer value given as 'issuer' when configuring SAML SP.
+ * @return issuer value with qualifier appended.
+ */
+ private String getIssuerWithQualifier(String issuer, String qualifier) {
+
+ return issuer + IdentityRegistryResources.QUALIFIER_ID + qualifier;
+ }
+
+ /**
+ * Get the issuer value by removing the qualifier.
+ *
+ * @param issuerWithQualifier issuer value saved in the registry.
+ * @return issuer value given as 'issuer' when configuring SAML SP.
+ */
+ private String getIssuerWithoutQualifier(String issuerWithQualifier) {
+
+ return StringUtils.substringBeforeLast(issuerWithQualifier, IdentityRegistryResources.QUALIFIER_ID);
+ }
+
+ private SAMLSSOServiceProviderDO resourceToObject(ResultSet resultSet) throws SQLException {
+
+ SAMLSSOServiceProviderDO serviceProviderDO = new SAMLSSOServiceProviderDO();
+
+ serviceProviderDO.setIssuer(resultSet.getString(ISSUER));
+ serviceProviderDO.setDefaultAssertionConsumerUrl(resultSet.getString(DEFAULT_ASSERTION_CONSUMER_URL));
+ serviceProviderDO.setNameIDFormat(resultSet.getString(NAME_ID_FORMAT));
+ serviceProviderDO.setCertAlias(resultSet.getString(CERT_ALIAS));
+ serviceProviderDO.setDoValidateSignatureInRequests(resultSet.getBoolean(REQ_SIG_VALIDATION));
+ serviceProviderDO.setDoSignResponse(resultSet.getBoolean(SIGN_RESPONSE));
+ serviceProviderDO.setDoSignAssertions(resultSet.getBoolean(SIGN_ASSERTIONS));
+ serviceProviderDO.setSigningAlgorithmUri(resultSet.getString(SIGNING_ALGO));
+ serviceProviderDO.setDigestAlgorithmUri(resultSet.getString(DIGEST_ALGO));
+ serviceProviderDO.setDoEnableEncryptedAssertion(resultSet.getBoolean(ENCRYPT_ASSERTION));
+ serviceProviderDO.setAssertionEncryptionAlgorithmUri(resultSet.getString(ASSERTION_ENCRYPTION_ALGO));
+ serviceProviderDO.setKeyEncryptionAlgorithmUri(resultSet.getString(KEY_ENCRYPTION_ALGO));
+ serviceProviderDO.setEnableAttributesByDefault(resultSet.getBoolean(ATTR_PROFILE_ENABLED));
+ serviceProviderDO.setAttributeConsumingServiceIndex(resultSet.getString(ATTR_SERVICE_INDEX));
+ serviceProviderDO.setDoSingleLogout(resultSet.getBoolean(SLO_PROFILE_ENABLED));
+ serviceProviderDO.setSloResponseURL(resultSet.getString(SLO_RESPONSE_URL));
+ serviceProviderDO.setSloRequestURL(resultSet.getString(SLO_REQUEST_URL));
+ serviceProviderDO.setIdPInitSSOEnabled(resultSet.getBoolean(IDP_INIT_SSO_ENABLED));
+ serviceProviderDO.setIdPInitSLOEnabled(resultSet.getBoolean(IDP_INIT_SLO_ENABLED));
+ serviceProviderDO.setAssertionQueryRequestProfileEnabled(resultSet.getBoolean(QUERY_REQUEST_PROFILE_ENABLED));
+ serviceProviderDO.setSamlECP(resultSet.getBoolean(ECP_ENABLED));
+ serviceProviderDO.setEnableSAML2ArtifactBinding(resultSet.getBoolean(ARTIFACT_BINDING_ENABLED));
+ serviceProviderDO.setDoValidateSignatureInArtifactResolve(
+ resultSet.getBoolean(ARTIFACT_RESOLVE_REQ_SIG_VALIDATION));
+ serviceProviderDO.setIdpEntityIDAlias(resultSet.getString(IDP_ENTITY_ID_ALIAS));
+ serviceProviderDO.setIssuerQualifier(resultSet.getString(ISSUER_QUALIFIER));
+ serviceProviderDO.setSupportedAssertionQueryRequestTypes(
+ resultSet.getString(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES));
+ serviceProviderDO.setDoFrontChannelLogout(!"BackChannel".equals(resultSet.getString(SLO_METHOD)));
+ if (serviceProviderDO.isDoFrontChannelLogout()) {
+ serviceProviderDO.setFrontChannelLogoutBinding(resultSet.getString(SLO_METHOD));
+ }
+
+ return serviceProviderDO;
+ }
+
+ private void addProperties(int serviceProviderId, SAMLSSOServiceProviderDO serviceProviderDO)
+ throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ List properties =
+ namedJdbcTemplate.executeQuery(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML_SSO_ATTR_BY_ID,
+ (resultSet, rowNumber) -> new ServiceProviderProperty(resultSet.getString(PROPERTY_NAME),
+ resultSet.getString(PROPERTY_VALUE)),
+ namedPreparedStatement -> namedPreparedStatement.setInt(SP_ID, serviceProviderId));
+ serviceProviderDO.addMultiValuedProperties(properties);
+ }
+
+ private void setUpdateServiceProviderParameters(NamedPreparedStatement statement,
+ SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws SQLException {
+
+ statement.setInt(TENANT_ID, tenantId);
+ statement.setString(ISSUER, serviceProviderDO.getIssuer());
+ statement.setString(DEFAULT_ASSERTION_CONSUMER_URL, serviceProviderDO.getDefaultAssertionConsumerUrl());
+ statement.setString(NAME_ID_FORMAT, serviceProviderDO.getNameIDFormat());
+ statement.setString(CERT_ALIAS, serviceProviderDO.getCertAlias());
+ statement.setBoolean(REQ_SIG_VALIDATION, serviceProviderDO.isDoValidateSignatureInRequests());
+ statement.setBoolean(SIGN_RESPONSE, serviceProviderDO.isDoSignResponse());
+ statement.setBoolean(SIGN_ASSERTIONS, serviceProviderDO.isDoSignAssertions());
+ statement.setString(SIGNING_ALGO, serviceProviderDO.getSigningAlgorithmUri());
+ statement.setString(DIGEST_ALGO, serviceProviderDO.getDigestAlgorithmUri());
+ statement.setBoolean(ENCRYPT_ASSERTION, serviceProviderDO.isDoEnableEncryptedAssertion());
+ statement.setString(ASSERTION_ENCRYPTION_ALGO, serviceProviderDO.getAssertionEncryptionAlgorithmUri());
+ statement.setString(KEY_ENCRYPTION_ALGO, serviceProviderDO.getKeyEncryptionAlgorithmUri());
+ statement.setBoolean(ATTR_PROFILE_ENABLED, serviceProviderDO.isEnableAttributesByDefault());
+ statement.setString(ATTR_SERVICE_INDEX, serviceProviderDO.getAttributeConsumingServiceIndex());
+ statement.setBoolean(SLO_PROFILE_ENABLED, serviceProviderDO.isDoSingleLogout());
+ statement.setString(SLO_METHOD, serviceProviderDO.getSingleLogoutMethod());
+ statement.setString(SLO_RESPONSE_URL, serviceProviderDO.getSloResponseURL());
+ statement.setString(SLO_REQUEST_URL, serviceProviderDO.getSloRequestURL());
+ statement.setBoolean(IDP_INIT_SSO_ENABLED, serviceProviderDO.isIdPInitSSOEnabled());
+ statement.setBoolean(IDP_INIT_SLO_ENABLED, serviceProviderDO.isIdPInitSLOEnabled());
+ statement.setBoolean(QUERY_REQUEST_PROFILE_ENABLED, serviceProviderDO.isAssertionQueryRequestProfileEnabled());
+ statement.setBoolean(ECP_ENABLED, serviceProviderDO.isSamlECP());
+ statement.setBoolean(ARTIFACT_BINDING_ENABLED, serviceProviderDO.isEnableSAML2ArtifactBinding());
+ statement.setBoolean(ARTIFACT_RESOLVE_REQ_SIG_VALIDATION,
+ serviceProviderDO.isDoValidateSignatureInArtifactResolve());
+ statement.setString(IDP_ENTITY_ID_ALIAS, serviceProviderDO.getIdpEntityIDAlias());
+ statement.setString(ISSUER_QUALIFIER, serviceProviderDO.getIssuerQualifier());
+ statement.setString(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES,
+ serviceProviderDO.getSupportedAssertionQueryRequestTypes());
+ statement.setTimeStamp(UPDATED_AT, new Timestamp(new Date().getTime()), CALENDAR);
+ }
+
+ private void setServiceProviderParameters(NamedPreparedStatement statement,
+ SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws SQLException {
+
+ Timestamp currentTime = new Timestamp(new Date().getTime());
+ statement.setInt(TENANT_ID, tenantId);
+ statement.setString(ISSUER, serviceProviderDO.getIssuer());
+ statement.setString(DEFAULT_ASSERTION_CONSUMER_URL, serviceProviderDO.getDefaultAssertionConsumerUrl());
+ statement.setString(NAME_ID_FORMAT, serviceProviderDO.getNameIDFormat());
+ statement.setString(CERT_ALIAS, serviceProviderDO.getCertAlias());
+ statement.setBoolean(REQ_SIG_VALIDATION, serviceProviderDO.isDoValidateSignatureInRequests());
+ statement.setBoolean(SIGN_RESPONSE, serviceProviderDO.isDoSignResponse());
+ statement.setBoolean(SIGN_ASSERTIONS, serviceProviderDO.isDoSignAssertions());
+ statement.setString(SIGNING_ALGO, serviceProviderDO.getSigningAlgorithmUri());
+ statement.setString(DIGEST_ALGO, serviceProviderDO.getDigestAlgorithmUri());
+ statement.setBoolean(ENCRYPT_ASSERTION, serviceProviderDO.isDoEnableEncryptedAssertion());
+ statement.setString(ASSERTION_ENCRYPTION_ALGO, serviceProviderDO.getAssertionEncryptionAlgorithmUri());
+ statement.setString(KEY_ENCRYPTION_ALGO, serviceProviderDO.getKeyEncryptionAlgorithmUri());
+ statement.setBoolean(ATTR_PROFILE_ENABLED, serviceProviderDO.isEnableAttributesByDefault());
+ statement.setString(ATTR_SERVICE_INDEX, serviceProviderDO.getAttributeConsumingServiceIndex());
+ statement.setBoolean(SLO_PROFILE_ENABLED, serviceProviderDO.isDoSingleLogout());
+ statement.setString(SLO_METHOD, serviceProviderDO.getSingleLogoutMethod());
+ statement.setString(SLO_RESPONSE_URL, serviceProviderDO.getSloResponseURL());
+ statement.setString(SLO_REQUEST_URL, serviceProviderDO.getSloRequestURL());
+ statement.setBoolean(IDP_INIT_SSO_ENABLED, serviceProviderDO.isIdPInitSSOEnabled());
+ statement.setBoolean(IDP_INIT_SLO_ENABLED, serviceProviderDO.isIdPInitSLOEnabled());
+ statement.setBoolean(QUERY_REQUEST_PROFILE_ENABLED, serviceProviderDO.isAssertionQueryRequestProfileEnabled());
+ statement.setBoolean(ECP_ENABLED, serviceProviderDO.isSamlECP());
+ statement.setBoolean(ARTIFACT_BINDING_ENABLED, serviceProviderDO.isEnableSAML2ArtifactBinding());
+ statement.setBoolean(ARTIFACT_RESOLVE_REQ_SIG_VALIDATION,
+ serviceProviderDO.isDoValidateSignatureInArtifactResolve());
+ statement.setString(IDP_ENTITY_ID_ALIAS, serviceProviderDO.getIdpEntityIDAlias());
+ statement.setString(ISSUER_QUALIFIER, serviceProviderDO.getIssuerQualifier());
+ statement.setString(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES,
+ serviceProviderDO.getSupportedAssertionQueryRequestTypes());
+ statement.setString(VERSION, SAML_SCHEMA_VERSION);
+ statement.setTimeStamp(CREATED_AT, currentTime, CALENDAR);
+ statement.setTimeStamp(UPDATED_AT, currentTime, CALENDAR);
+ }
+
+ private int processGetServiceProviderId(String issuer, int tenantId) throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ Integer serviceProviderId =
+ namedJdbcTemplate.fetchSingleRecord(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML_SP_ID_BY_ISSUER,
+ (resultSet, rowNumber) -> resultSet.getInt(ID), namedPreparedStatement -> {
+ namedPreparedStatement.setString(ISSUER, issuer);
+ namedPreparedStatement.setInt(TENANT_ID, tenantId);
+ });
+ if (serviceProviderId == null) {
+ throw new DataAccessException("No record found for the given issuer: " + issuer);
+ }
+ return serviceProviderId.intValue();
+ }
+
+ private void processAddServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO,int tenantId) throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ namedJdbcTemplate.executeInsert(SAMLSSOServiceProviderConstants.SQLQueries.ADD_SAML2_SSO_CONFIG,
+ namedPreparedStatement -> setServiceProviderParameters(namedPreparedStatement, serviceProviderDO, tenantId),
+ serviceProviderDO, false);
+ }
+
+ private void processAddSPProperties(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws DataAccessException {
+
+ List properties = serviceProviderDO.getMultiValuedProperties();
+ int serviceProviderId = processGetServiceProviderId(serviceProviderDO.getIssuer(), tenantId);
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+
+ namedJdbcTemplate.executeBatchInsert(SAMLSSOServiceProviderConstants.SQLQueries.ADD_SAML_SSO_ATTR,
+ (namedPreparedStatement -> {
+ for (ServiceProviderProperty property : properties) {
+ namedPreparedStatement.setInt(SP_ID, serviceProviderId);
+ namedPreparedStatement.setString(PROPERTY_NAME, property.getKey());
+ namedPreparedStatement.setString(PROPERTY_VALUE, property.getValue());
+ namedPreparedStatement.addBatch();
+ }
+ }), serviceProviderDO);
+ }
+
+ private void processUpdateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int serviceProviderId, int tenantId)
+ throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.UPDATE_SAML2_SSO_CONFIG,
+ namedPreparedStatement -> {
+ namedPreparedStatement.setInt(ID, serviceProviderId);
+ setUpdateServiceProviderParameters(namedPreparedStatement, serviceProviderDO, tenantId);
+ });
+ }
+
+ private void processUpdateSPProperties(SAMLSSOServiceProviderDO serviceProviderDO, int serviceProviderId)
+ throws DataAccessException {
+
+ List properties = serviceProviderDO.getMultiValuedProperties();
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+
+ namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.DELETE_SAML_SSO_ATTR_BY_ID,
+ namedPreparedStatement -> namedPreparedStatement.setInt(SP_ID, serviceProviderId));
+
+ namedJdbcTemplate.executeBatchInsert(SAMLSSOServiceProviderConstants.SQLQueries.ADD_SAML_SSO_ATTR,
+ (namedPreparedStatement -> {
+ for (ServiceProviderProperty property : properties) {
+ namedPreparedStatement.setInt(SP_ID, serviceProviderId);
+ namedPreparedStatement.setString(PROPERTY_NAME, property.getKey());
+ namedPreparedStatement.setString(PROPERTY_VALUE, property.getValue());
+ namedPreparedStatement.addBatch();
+ }
+ }), serviceProviderDO);
+ }
+
+ private SAMLSSOServiceProviderDO processGetServiceProvider(String issuer, int tenantId) throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ SAMLSSOServiceProviderDO serviceProviderDO = namedJdbcTemplate.fetchSingleRecord(
+ SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML2_SSO_CONFIG_BY_ISSUER,
+ (resultSet, rowNumber) -> resourceToObject(resultSet), namedPreparedStatement -> {
+ namedPreparedStatement.setString(ISSUER, issuer);
+ namedPreparedStatement.setInt(TENANT_ID, tenantId);
+ });
+
+ if (serviceProviderDO != null) {
+ addProperties(processGetServiceProviderId(issuer, tenantId), serviceProviderDO);
+ }
+ return serviceProviderDO;
+ }
+
+ private List processGetServiceProviders(int tenantId) throws DataAccessException {
+
+ List serviceProvidersList;
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ serviceProvidersList =
+ namedJdbcTemplate.executeQuery(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML2_SSO_CONFIGS,
+ (resultSet, rowNumber) -> resourceToObject(resultSet),
+ namedPreparedStatement -> namedPreparedStatement.setInt(TENANT_ID, tenantId));
+
+ for (SAMLSSOServiceProviderDO serviceProviderDO : serviceProvidersList) {
+ addProperties(processGetServiceProviderId(serviceProviderDO.getIssuer(), tenantId), serviceProviderDO);
+ }
+ return serviceProvidersList;
+ }
+
+ private void processDeleteServiceProvider(String issuer, int tenantId) throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+
+ namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.DELETE_SAML2_SSO_CONFIG_BY_ISSUER,
+ namedPreparedStatement -> {
+ namedPreparedStatement.setString(ISSUER, issuer);
+ namedPreparedStatement.setInt(TENANT_ID, tenantId);
+ });
+
+ namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.DELETE_SAML_SSO_ATTR,
+ namedPreparedStatement -> {
+ namedPreparedStatement.setString(ISSUER, issuer);
+ namedPreparedStatement.setInt(TENANT_ID, tenantId);
+ });
+ }
+
+ /**
+ * Returns the {@link java.security.cert.Certificate} which should used to validate the requests
+ * for the given service provider.
+ *
+ * @param serviceProviderDO service provider information object.
+ * @param tenant tenant Domain.
+ * @return The X509 certificate used to validate the requests.
+ * @throws DataAccessException If an error occurs while retrieving the certificate Id.
+ * @throws CertificateRetrievingException If an error occurs while retrieving the certificate.
+ */
+ private X509Certificate getApplicationCertificate(SAMLSSOServiceProviderDO serviceProviderDO, Tenant tenant)
+ throws CertificateRetrievingException, DataAccessException {
+
+ // Check whether there is a certificate stored against the service provider (in the database).
+ int applicationCertificateId = getApplicationCertificateId(serviceProviderDO.getIssuer(), tenant.getId());
+
+ CertificateRetriever certificateRetriever;
+ String certificateIdentifier;
+ if (applicationCertificateId != -1) {
+ certificateRetriever = new DatabaseCertificateRetriever();
+ certificateIdentifier = Integer.toString(applicationCertificateId);
+ } else {
+ certificateRetriever = new KeyStoreCertificateRetriever();
+ certificateIdentifier = serviceProviderDO.getCertAlias();
+ }
+
+ return certificateRetriever.getCertificate(certificateIdentifier, tenant);
+ }
+
+ /**
+ * Returns the certificate reference ID for the given issuer (Service Provider) if there is one.
+ *
+ * @param issuer the issuer of the service provider.
+ * @param tenantId the tenant ID.
+ * @return the certificate reference ID, or -1 if no certificate is found.
+ * @throws SQLException
+ */
+ private int getApplicationCertificateId(String issuer, int tenantId) throws DataAccessException {
+
+ NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate();
+ String sqlStmt =
+ isH2DB() ? SAMLSSOServiceProviderConstants.SQLQueries.QUERY_TO_GET_APPLICATION_CERTIFICATE_ID_H2 :
+ SAMLSSOServiceProviderConstants.SQLQueries.QUERY_TO_GET_APPLICATION_CERTIFICATE_ID;
+ Integer certificateId =
+ namedJdbcTemplate.fetchSingleRecord(sqlStmt, (resultSet, rowNumber) -> resultSet.getInt(1),
+ namedPreparedStatement -> {
+ namedPreparedStatement.setString(1, CERTIFICATE_PROPERTY_NAME);
+ namedPreparedStatement.setString(2, issuer);
+ namedPreparedStatement.setInt(3, tenantId);
+ });
+
+ return certificateId != null ? certificateId : -1;
+ }
+
+}
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java
index f07d50eb03b5..109a173bcf33 100644
--- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java
@@ -67,9 +67,10 @@ public class RegistrySAMLSSOServiceProviderDAOImpl extends AbstractDAO getMultiValuedProperties() {
+
+ List multiValuedProperties = new ArrayList<>();
+
+ // Multi-valued attributes.
+ getAssertionConsumerUrlList().forEach(assertionConUrl ->
+ putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.ASSERTION_CONSUMER_URLS.toString(),
+ assertionConUrl));
+ getRequestedRecipientsList().forEach(requestedRecipient ->
+ putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.RECIPIENTS.toString(),
+ requestedRecipient));
+ getRequestedAudiencesList().forEach(requestedAudience ->
+ putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.AUDIENCES.toString(),
+ requestedAudience));
+ getIdpInitSLOReturnToURLList().forEach(idpInitSLOReturnToURL ->
+ putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.SLO_RETURN_TO_URLS.toString(),
+ idpInitSLOReturnToURL));
+
+ return multiValuedProperties;
+ }
+
+ /**
+ * Add a list of multivalued properties.
+ *
+ * @param multiValuedProperties List of ServiceProviderProperty.
+ */
+ public void addMultiValuedProperties(List multiValuedProperties) {
+
+ if (multiValuedProperties == null) {
+ return;
+ }
+
+ multiValuedProperties.forEach(this::addMultiValuedProperty);
+ }
+
+ /**
+ * Add a multivalued property.
+ *
+ * @param multiValuedProperty ServiceProviderProperty.
+ */
+ private void addMultiValuedProperty(ServiceProviderProperty multiValuedProperty) {
+
+ if (multiValuedProperty == null) {
+ return;
+ }
+ String key = multiValuedProperty.getKey();
+ String value = multiValuedProperty.getValue();
+
+ if (MultiValuedPropertyKey.ASSERTION_CONSUMER_URLS.toString().equals(key)) {
+ List attributeList = getAssertionConsumerUrlList();
+ if (attributeList.isEmpty()) {
+ attributeList = new ArrayList<>();
+ }
+ attributeList.add(value);
+ setAssertionConsumerUrls(attributeList);
+ } else if (MultiValuedPropertyKey.RECIPIENTS.toString().equals(key)) {
+ List attributeList = getRequestedRecipientsList();
+ if (attributeList.isEmpty()) {
+ attributeList = new ArrayList<>();
+ }
+ attributeList.add(value);
+ setRequestedRecipients(attributeList);
+ } else if (MultiValuedPropertyKey.AUDIENCES.toString().equals(key)) {
+ List attributeList = getRequestedAudiencesList();
+ if (attributeList.isEmpty()) {
+ attributeList = new ArrayList<>();
+ }
+ attributeList.add(value);
+ setRequestedAudiences(attributeList);
+ } else if (MultiValuedPropertyKey.SLO_RETURN_TO_URLS.toString().equals(key)) {
+ List attributeList = getIdpInitSLOReturnToURLList();
+ if (attributeList.isEmpty()) {
+ attributeList = new ArrayList<>();
+ }
+ attributeList.add(value);
+ setIdpInitSLOReturnToURLs(attributeList);
+ }
+ }
+
+ /**
+ * Put a key value pair to a list if the value is not null.
+ *
+ * @param list List of ServiceProviderProperty.
+ * @param key Key.
+ * @param value Value.
+ */
+ private void putIfNotNull(List list, String key, String value) {
+
+ if (StringUtils.isNotBlank(value)) {
+ list.add(new ServiceProviderProperty(key, value));
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SAMLSSOServiceProviderDO that = (SAMLSSOServiceProviderDO) o;
+ return doSingleLogout == that.doSingleLogout &&
+ doSignResponse == that.doSignResponse &&
+ doSignAssertions == that.doSignAssertions &&
+ enableAttributesByDefault == that.enableAttributesByDefault &&
+ isIdPInitSSOEnabled == that.isIdPInitSSOEnabled &&
+ idPInitSLOEnabled == that.idPInitSLOEnabled &&
+ doEnableEncryptedAssertion == that.doEnableEncryptedAssertion &&
+ doValidateSignatureInRequests == that.doValidateSignatureInRequests &&
+ doValidateSignatureInArtifactResolve == that.doValidateSignatureInArtifactResolve &&
+ enableSAML2ArtifactBinding == that.enableSAML2ArtifactBinding &&
+ samlECP == that.samlECP &&
+ doFrontChannelLogout == that.doFrontChannelLogout &&
+ Objects.equals(tenantDomain, that.tenantDomain) &&
+ Objects.equals(issuer, that.issuer) &&
+ Objects.equals(issuerQualifier, that.issuerQualifier) &&
+ Objects.equals(assertionConsumerUrl, that.assertionConsumerUrl) &&
+ Arrays.equals(assertionConsumerUrls, that.assertionConsumerUrls) &&
+ Objects.equals(defaultAssertionConsumerUrl, that.defaultAssertionConsumerUrl) &&
+ Objects.equals(certAlias, that.certAlias) &&
+ Objects.equals(sloResponseURL, that.sloResponseURL) &&
+ Objects.equals(sloRequestURL, that.sloRequestURL) &&
+ Objects.equals(loginPageURL, that.loginPageURL) &&
+ Objects.equals(attributeConsumingServiceIndex, that.attributeConsumingServiceIndex) &&
+ Arrays.equals(requestedClaims, that.requestedClaims) &&
+ Arrays.equals(requestedAudiences, that.requestedAudiences) &&
+ Arrays.equals(requestedRecipients, that.requestedRecipients) &&
+ Objects.equals(nameIdClaimUri, that.nameIdClaimUri) &&
+ Objects.equals(nameIDFormat, that.nameIDFormat) &&
+ Arrays.equals(idpInitSLOReturnToURLs, that.idpInitSLOReturnToURLs) &&
+ Objects.equals(signingAlgorithmUri, that.signingAlgorithmUri) &&
+ Objects.equals(digestAlgorithmUri, that.digestAlgorithmUri) &&
+ Objects.equals(assertionEncryptionAlgorithmUri, that.assertionEncryptionAlgorithmUri) &&
+ Objects.equals(keyEncryptionAlgorithmUri, that.keyEncryptionAlgorithmUri) &&
+ Objects.equals(signingCertificate, that.signingCertificate) &&
+ Objects.equals(encryptionCertificate, that.encryptionCertificate) &&
+ Objects.equals(idpEntityIDAlias, that.idpEntityIDAlias) &&
+ Objects.equals(frontChannelLogoutBinding, that.frontChannelLogoutBinding);
+ }
+
+ @Override
+ public int hashCode() {
+
+ int h = Objects.hash(tenantDomain, issuer, issuerQualifier, assertionConsumerUrl, defaultAssertionConsumerUrl,
+ certAlias, sloResponseURL, sloRequestURL, doSingleLogout, loginPageURL, doSignResponse,
+ doSignAssertions, attributeConsumingServiceIndex, enableAttributesByDefault, nameIdClaimUri,
+ nameIDFormat, isIdPInitSSOEnabled, idPInitSLOEnabled, doEnableEncryptedAssertion,
+ doValidateSignatureInRequests, doValidateSignatureInArtifactResolve, signingAlgorithmUri,
+ digestAlgorithmUri, assertionEncryptionAlgorithmUri, keyEncryptionAlgorithmUri, signingCertificate,
+ encryptionCertificate, isAssertionQueryRequestProfileEnabled, supportedAssertionQueryRequestTypes,
+ enableSAML2ArtifactBinding, samlECP, idpEntityIDAlias, doFrontChannelLogout, frontChannelLogoutBinding);
+ h = 31 * h + Arrays.hashCode(assertionConsumerUrls);
+ h = 31 * h + Arrays.hashCode(requestedClaims);
+ h = 31 * h + Arrays.hashCode(requestedAudiences);
+ h = 31 * h + Arrays.hashCode(requestedRecipients);
+ h = 31 * h + Arrays.hashCode(idpInitSLOReturnToURLs);
+ return h;
+ }
}
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/model/ServiceProviderProperty.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/model/ServiceProviderProperty.java
new file mode 100644
index 000000000000..5d2fadf6aff8
--- /dev/null
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/model/ServiceProviderProperty.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * 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
+ *
+ * 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.
+ */
+
+package org.wso2.carbon.identity.core.model;
+
+/**
+ * Represents a service provider property with a key-value pair storing ASSERTION_CONSUMER_URLS, AUDIENCES, RECIPIENTS,
+ * SLO_RETURN_TO_URLS properties for a service provider.
+ */
+public class ServiceProviderProperty {
+
+ private String key;
+ private String value;
+
+ public ServiceProviderProperty(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ * Get the key of the tuple.
+ *
+ * @return Key of the tuple.
+ */
+ public String getKey() {
+ return this.key;
+ }
+
+ /**
+ * Get the value of the tuple.
+ *
+ * @return Value of the tuple.
+ */
+ public String getValue() {
+ return this.value;
+ }
+
+}
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManagerTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManagerTest.java
new file mode 100644
index 000000000000..48f422e68400
--- /dev/null
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManagerTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * 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
+ *
+ * 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.
+ */
+
+package org.wso2.carbon.identity.core;
+
+import org.apache.commons.lang.StringUtils;
+import org.mockito.MockedStatic;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate;
+import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException;
+import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException;
+import org.wso2.carbon.identity.base.IdentityException;
+import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO;
+import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
+import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
+import org.wso2.carbon.identity.core.util.IdentityUtil;
+import org.wso2.carbon.identity.core.util.JdbcUtils;
+import org.wso2.carbon.identity.core.util.TestUtils;
+
+import java.sql.Connection;
+
+import javax.sql.DataSource;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.lenient;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.testng.Assert.assertEquals;
+
+import static org.testng.Assert.assertTrue;
+import static org.wso2.carbon.identity.core.constant.TestConstants.*;
+import static org.mockito.ArgumentMatchers.any;
+
+/**
+ * This class tests the methods of the SAMLSSOServiceProviderManager class.
+ */
+@Listeners(MockitoTestNGListener.class)
+public class SAMLSSOServiceProviderManagerTest {
+
+ private MockedStatic identityUtil;
+ private MockedStatic identityTenantUtil;
+ private MockedStatic identityDatabaseUtil;
+
+ public SAMLSSOServiceProviderManager samlSSOServiceProviderManager;
+
+ public SAMLSSOServiceProviderDO sampleServiceProvider1;
+ public SAMLSSOServiceProviderDO sampleServiceProvider2;
+ public SAMLSSOServiceProviderDO invalidServiceProviderDO;
+
+ @BeforeMethod
+ public void setUp() throws Exception {
+
+ samlSSOServiceProviderManager = new SAMLSSOServiceProviderManager();
+ sampleServiceProvider1 = createServiceProviderDO(ISSUER1);
+ sampleServiceProvider2 = createServiceProviderDO(ISSUER2);
+ invalidServiceProviderDO = createServiceProviderDO(null);
+
+ TestUtils.initiateH2Base();
+ DataSource dataSource = mock(DataSource.class);
+ identityDatabaseUtil = mockStatic(IdentityDatabaseUtil.class);
+ identityUtil = mockStatic(IdentityUtil.class);
+ identityTenantUtil = mockStatic(IdentityTenantUtil.class);
+
+ identityUtil.when(() -> IdentityUtil.getProperty("SAMLStorage.Type")).thenReturn("database");
+ identityDatabaseUtil.when(IdentityDatabaseUtil::getDataSource).thenReturn(dataSource);
+
+ Connection connection = TestUtils.getConnection();
+ Connection spyConnection = TestUtils.spyConnection(connection);
+
+ lenient().when(dataSource.getConnection()).thenReturn(spyConnection);
+ lenient().doNothing().when(spyConnection).close();
+
+ }
+
+ @AfterMethod
+ public void tearDown() throws Exception {
+
+ identityUtil.close();
+ identityTenantUtil.close();
+ identityDatabaseUtil.close();
+ TestUtils.closeH2Base();
+ }
+
+ @Test
+ public void testAddServiceProvider() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ SAMLSSOServiceProviderDO serviceProviderFromStorage =
+ samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID);
+ assertEquals(serviceProviderFromStorage, sampleServiceProvider1);
+ }
+
+ @Test
+ public void testAddEmptyServiceProvider() {
+
+ assertThrows(IdentityException.class,
+ () -> samlSSOServiceProviderManager.addServiceProvider(invalidServiceProviderDO, TENANT_ID));
+ }
+
+ @Test
+ public void addServiceProviderWithDuplicateIssuer() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ System.out.println("sampleServiceProvider iss " + sampleServiceProvider1);
+ assertFalse(samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID));
+ }
+
+ @Test
+ public void testAddServiceProviderWithException() throws Exception {
+
+ SAMLSSOServiceProviderDO serviceProviderDO = createServiceProviderDO(ISSUER1);
+
+ try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) {
+ NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class);
+ jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate);
+ doThrow(new TransactionException("Transaction failed")).when(namedJdbcTemplate).withTransaction(any());
+
+ assertThrows(IdentityException.class,
+ () -> samlSSOServiceProviderManager.addServiceProvider(serviceProviderDO, TENANT_ID));
+ }
+ }
+
+ @Test
+ public void testUpdateServiceProvider() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ sampleServiceProvider1.setDoSingleLogout(UPDATED_DO_SINGLE_LOGOUT);
+ sampleServiceProvider1.setRequestedRecipients(UPDATED_REQUESTED_RECIPIENTS);
+
+ samlSSOServiceProviderManager.updateServiceProvider(sampleServiceProvider1, getIssuerWithQualifier(ISSUER1),
+ TENANT_ID);
+
+ SAMLSSOServiceProviderDO updatedServiceProvider =
+ samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID);
+ assertEquals(sampleServiceProvider1, updatedServiceProvider);
+ }
+
+ @Test
+ public void testUpdateServiceProviderWithDuplicateIssuer() throws Exception {
+
+ sampleServiceProvider1 = createServiceProviderDO(ISSUER1);
+ sampleServiceProvider2 = createServiceProviderDO(ISSUER2);
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider2, TENANT_ID);
+
+ sampleServiceProvider2.setIssuer(getIssuerWithQualifier(ISSUER1));
+ assertFalse(samlSSOServiceProviderManager.updateServiceProvider(sampleServiceProvider2, ISSUER2, TENANT_ID));
+ }
+
+ @Test
+ public void testUpdateWithInvalidServiceProvider() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ assertThrows(IdentityException.class,
+ () -> samlSSOServiceProviderManager.updateServiceProvider(invalidServiceProviderDO,
+ getIssuerWithQualifier(ISSUER1), TENANT_ID));
+ }
+
+ @Test
+ public void testUpdateServiceProviderWithException() throws Exception {
+
+ SAMLSSOServiceProviderDO serviceProviderDO = createServiceProviderDO(ISSUER1);
+
+ try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) {
+ NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class);
+ jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate);
+ lenient().doThrow(new TransactionException("Transaction failed")).when(namedJdbcTemplate)
+ .withTransaction(any());
+
+ assertThrows(IdentityException.class,
+ () -> samlSSOServiceProviderManager.updateServiceProvider(serviceProviderDO,
+ getIssuerWithQualifier(ISSUER1), TENANT_ID));
+ }
+ }
+
+ @Test
+ public void testGetServiceProviders() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ sampleServiceProvider2 = createServiceProviderDO(ISSUER2);
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider2, TENANT_ID);
+
+ SAMLSSOServiceProviderDO[] serviceProviders = samlSSOServiceProviderManager.getServiceProviders(TENANT_ID);
+
+ assertEquals(serviceProviders, new SAMLSSOServiceProviderDO[]{sampleServiceProvider1, sampleServiceProvider2});
+ }
+
+ @Test
+ public void testGetServiceProvidersWithDataAccessException() throws Exception {
+
+ try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) {
+ NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class);
+ jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate);
+ doThrow(new DataAccessException("Data access error")).when(namedJdbcTemplate)
+ .executeQuery(any(), any(), any());
+
+ assertThrows(IdentityException.class, () -> samlSSOServiceProviderManager.getServiceProviders(TENANT_ID));
+ }
+ }
+
+ @Test
+ public void testGetServiceProvider() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+
+ SAMLSSOServiceProviderDO serviceProviderFromStorage =
+ samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID);
+
+ assertEquals(serviceProviderFromStorage, sampleServiceProvider1);
+ }
+
+ @Test
+ public void testProcessGetServiceProviderWithDataAccessException() throws Exception {
+
+ try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) {
+ NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class);
+ jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate);
+ doThrow(new DataAccessException("Data access error")).when(namedJdbcTemplate)
+ .fetchSingleRecord(any(), any(), any());
+
+ assertThrows(IdentityException.class,
+ () -> samlSSOServiceProviderManager.getServiceProvider(ISSUER1, TENANT_ID));
+ }
+ }
+
+ @Test
+ public void testIsServiceProviderExists() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ assertTrue(samlSSOServiceProviderManager.isServiceProviderExists(getIssuerWithQualifier(ISSUER1), TENANT_ID));
+ }
+
+ @Test
+ public void testNonExistingIsServiceProviderExists() throws Exception {
+
+ assertFalse(samlSSOServiceProviderManager.isServiceProviderExists(getIssuerWithQualifier(ISSUER1), TENANT_ID));
+ }
+
+ @Test
+ public void testRemoveServiceProvider() throws Exception {
+
+ samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID);
+ assertTrue(samlSSOServiceProviderManager.removeServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID));
+ assertNull(samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID));
+
+ }
+
+ @Test
+ public void testRemoveNonExistingServiceProvider() throws Exception {
+
+ assertFalse(samlSSOServiceProviderManager.removeServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID));
+ }
+
+ @Test
+ public void testRemoveEmptyServiceProvider() {
+
+ assertThrows(IllegalArgumentException.class,
+ () -> samlSSOServiceProviderManager.removeServiceProvider(null, TENANT_ID));
+ }
+
+ @Test
+ public void testUploadServiceProvider() throws Exception {
+
+ samlSSOServiceProviderManager.uploadServiceProvider(sampleServiceProvider1, TENANT_ID);
+
+ SAMLSSOServiceProviderDO serviceProviderFromStorage =
+ samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID);
+ assertEquals(serviceProviderFromStorage, sampleServiceProvider1);
+ }
+
+ @Test
+ public void testUploadDuplicateServiceProvider() throws Exception {
+
+ samlSSOServiceProviderManager.uploadServiceProvider(sampleServiceProvider1, TENANT_ID);
+ assertThrows(IdentityException.class,
+ () -> samlSSOServiceProviderManager.uploadServiceProvider(sampleServiceProvider1, TENANT_ID));
+ }
+
+ @Test
+ public void testUploadServiceProviderWithDataAccessException() throws Exception {
+
+ SAMLSSOServiceProviderDO serviceProviderDO = createServiceProviderDO(ISSUER1);
+
+ try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) {
+ NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class);
+ jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate);
+ doThrow(new DataAccessException("Data access error")).when(namedJdbcTemplate).withTransaction(any());
+
+ assertThrows(IdentityException.class,
+ () -> samlSSOServiceProviderManager.uploadServiceProvider(serviceProviderDO, TENANT_ID));
+ }
+ }
+
+ private SAMLSSOServiceProviderDO createServiceProviderDO(String issuer) {
+
+ SAMLSSOServiceProviderDO serviceProviderDO = new SAMLSSOServiceProviderDO();
+ serviceProviderDO.setIssuer(issuer);
+ serviceProviderDO.setIssuerQualifier(ISSUER_QUALIFIER);
+ serviceProviderDO.setAssertionConsumerUrls(ASSERTION_CONSUMER_URLS);
+ serviceProviderDO.setDefaultAssertionConsumerUrl(DEFAULT_ASSERTION_CONSUMER_URL);
+ serviceProviderDO.setCertAlias(CERT_ALIAS);
+ serviceProviderDO.setSloResponseURL(SLO_RESPONSE_URL);
+ serviceProviderDO.setSloRequestURL(SLO_REQUEST_URL);
+ serviceProviderDO.setDoSingleLogout(DO_SINGLE_LOGOUT);
+ serviceProviderDO.setDoSignResponse(DO_SIGN_RESPONSE);
+ serviceProviderDO.setDoSignAssertions(DO_SIGN_ASSERTIONS);
+ serviceProviderDO.setAttributeConsumingServiceIndex(ATTRIBUTE_CONSUMING_SERVICE_INDEX);
+ serviceProviderDO.setRequestedAudiences(REQUESTED_AUDIENCES);
+ serviceProviderDO.setRequestedRecipients(REQUESTED_RECIPIENTS);
+ serviceProviderDO.setEnableAttributesByDefault(ENABLE_ATTRIBUTES_BY_DEFAULT);
+ serviceProviderDO.setNameIDFormat(NAME_ID_FORMAT);
+ serviceProviderDO.setIdPInitSSOEnabled(IS_IDP_INIT_SSO_ENABLED);
+ serviceProviderDO.setIdPInitSLOEnabled(IDP_INIT_SLO_ENABLED);
+ serviceProviderDO.setIdpInitSLOReturnToURLs(IDP_INIT_SLO_RETURN_TO_URLS);
+ serviceProviderDO.setDoEnableEncryptedAssertion(DO_ENABLE_ENCRYPTED_ASSERTION);
+ serviceProviderDO.setDoValidateSignatureInRequests(DO_VALIDATE_SIGNATURE_IN_REQUESTS);
+ serviceProviderDO.setDoValidateSignatureInArtifactResolve(DO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE);
+ serviceProviderDO.setSigningAlgorithmUri(SIGNING_ALGORITHM_URI);
+ serviceProviderDO.setDigestAlgorithmUri(DIGEST_ALGORITHM_URI);
+ serviceProviderDO.setAssertionEncryptionAlgorithmUri(ASSERTION_ENCRYPTION_ALGORITHM_URI);
+ serviceProviderDO.setKeyEncryptionAlgorithmUri(KEY_ENCRYPTION_ALGORITHM_URI);
+ serviceProviderDO.setAssertionQueryRequestProfileEnabled(IS_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED);
+ serviceProviderDO.setSupportedAssertionQueryRequestTypes(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES);
+ serviceProviderDO.setEnableSAML2ArtifactBinding(ENABLE_SAML2_ARTIFACT_BINDING);
+ serviceProviderDO.setSamlECP(SAML_ECP);
+ serviceProviderDO.setIdpEntityIDAlias(IDP_ENTITY_ID_ALIAS);
+ serviceProviderDO.setDoFrontChannelLogout(DO_FRONT_CHANNEL_LOGOUT);
+ serviceProviderDO.setFrontChannelLogoutBinding(FRONT_CHANNEL_LOGOUT_BINDING);
+
+ return serviceProviderDO;
+ }
+
+ public String getIssuerWithQualifier(String issuer) {
+
+ return StringUtils.isNotBlank(ISSUER_QUALIFIER) ?
+ issuer + IdentityRegistryResources.QUALIFIER_ID + ISSUER_QUALIFIER : issuer;
+ }
+}
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/constant/TestConstants.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/constant/TestConstants.java
new file mode 100644
index 000000000000..2d0cf51c10a6
--- /dev/null
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/constant/TestConstants.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * 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
+ *
+ * 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.
+ */
+
+package org.wso2.carbon.identity.core.constant;
+
+/**
+ * Test constants for SAMLSSOServiceProvider tests.
+ */
+public class TestConstants {
+
+ public static final int TENANT_ID = 1;
+ public static final String ISSUER1 = "issuer1";
+ public static final String ISSUER2 = "issuer2";
+ public static final String ISSUER_QUALIFIER = "issuerQualifier";
+ public static final String[] ASSERTION_CONSUMER_URLS = {"http://localhost:8080/acs", "http://localhost:8080/acs1"};
+ public static final String DEFAULT_ASSERTION_CONSUMER_URL = "http://localhost:8080/acs";
+ public static final String CERT_ALIAS = "wso2carbon";
+ public static final String SLO_RESPONSE_URL = "http://localhost:8080/sloResponse";
+ public static final String SLO_REQUEST_URL = "http://localhost:8080/sloRequest";
+ public static final boolean DO_SINGLE_LOGOUT = true;
+ public static final boolean DO_SIGN_RESPONSE = true;
+ public static final boolean DO_SIGN_ASSERTIONS = true;
+ public static final String ATTRIBUTE_CONSUMING_SERVICE_INDEX = "index";
+ public static final String[] REQUESTED_AUDIENCES = {"audience1", "audience2"};
+ public static final String[] REQUESTED_RECIPIENTS = {"recipient1", "recipient2"};
+ public static final boolean ENABLE_ATTRIBUTES_BY_DEFAULT = true;
+ public static final String NAME_ID_FORMAT = "nameIDFormat";
+ public static final boolean IS_IDP_INIT_SSO_ENABLED = true;
+ public static final boolean IDP_INIT_SLO_ENABLED = true;
+ public static final String[] IDP_INIT_SLO_RETURN_TO_URLS =
+ {"http://localhost:8080/returnTo1", "http://localhost:8080/returnTo2"};
+ public static final boolean DO_ENABLE_ENCRYPTED_ASSERTION = false;
+ public static final boolean DO_VALIDATE_SIGNATURE_IN_REQUESTS = false;
+ public static final boolean DO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE = false;
+ public static final String SIGNING_ALGORITHM_URI = "signingAlgorithmUri";
+ public static final String DIGEST_ALGORITHM_URI = "digestAlgorithmUri";
+ public static final String ASSERTION_ENCRYPTION_ALGORITHM_URI = "assertionEncryptionAlgorithmUri";
+ public static final String KEY_ENCRYPTION_ALGORITHM_URI = "keyEncryptionAlgorithmUri";
+ public static final boolean IS_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED = true;
+ public static final String SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES = "supportedTypes";
+ public static final boolean ENABLE_SAML2_ARTIFACT_BINDING = true;
+ public static final boolean SAML_ECP = true;
+ public static final String IDP_ENTITY_ID_ALIAS = "idpEntityIDAlias";
+ public static final boolean DO_FRONT_CHANNEL_LOGOUT = true;
+ public static final String FRONT_CHANNEL_LOGOUT_BINDING = "frontChannelLogoutBinding";
+
+ public static final boolean UPDATED_DO_SINGLE_LOGOUT = false;
+ public static final String[] UPDATED_REQUESTED_RECIPIENTS = {"updatedRecipient1", "updatedRecipient2"};
+}
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java
index 6b3636f4744a..a298e8a566eb 100644
--- a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java
@@ -64,6 +64,7 @@
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import static org.wso2.carbon.identity.core.constant.TestConstants.TENANT_ID;
/**
* Test class for SAMLSSOServiceProviderDAO.
@@ -80,7 +81,6 @@ public class SAMLSSOServiceProviderDAOTest {
private Map> dummyPropertiesWithAnIssuerQualifier;
private MockedStatic transaction;
private MockedStatic identityTenantUtil;
- private static final int TENANT_ID = 1;
@BeforeMethod
public void setUp() throws Exception {
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java
index 0df52c6d7ad2..a217b1aa387c 100644
--- a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java
@@ -26,6 +26,9 @@
import static org.testng.Assert.assertTrue;
+/**
+ * This class tests the methods of the SAMLServiceProviderPersistenceManagerFactory class.
+ */
public class SAMLServiceProviderPersistenceManagerFactoryTest {
private SAMLServiceProviderPersistenceManagerFactory factory;
@@ -49,7 +52,7 @@ public void testGetSAMLServiceProviderPersistenceManagerWithDefaultStorage() thr
setPrivateStaticField(SAMLServiceProviderPersistenceManagerFactory.class, "SAML_STORAGE_TYPE", "database");
SAMLSSOServiceProviderDAO samlSSOServiceProviderDAO = factory.getSAMLServiceProviderPersistenceManager();
-// assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl);
+ assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl);
}
@Test
@@ -63,9 +66,10 @@ public void testGetSAMLServiceProviderPersistenceManagerWithRegistryStorage() th
@Test
public void testGetSAMLServiceProviderPersistenceManagerWithHybridStorage() throws Exception {
+ //TODO : Change test to check for HybridSAMLSSOServiceProviderDAOImpl once implemented.
setPrivateStaticField(SAMLServiceProviderPersistenceManagerFactory.class, "SAML_STORAGE_TYPE", "hybrid");
SAMLSSOServiceProviderDAO samlSSOServiceProviderDAO = factory.getSAMLServiceProviderPersistenceManager();
-// assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl);
+ assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl);
}
private void setPrivateStaticField(Class> clazz, String fieldName, Object newValue)
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/TestUtils.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/TestUtils.java
new file mode 100644
index 000000000000..7d0c9fe1b252
--- /dev/null
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/TestUtils.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * 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
+ *
+ * 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.
+ */
+
+package org.wso2.carbon.identity.core.util;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.lang.StringUtils;
+
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.Mockito.spy;
+
+/**
+ * Utility functions for testing SAMLSSOServiceProviderManager class.
+ */
+public class TestUtils {
+
+ public static final String DB_NAME = "SAMLSSOServiceProviderManagerDB";
+ public static final String H2_SCRIPT_NAME = "h2.sql";
+ public static Map dataSourceMap = new HashMap<>();
+
+ public static Connection spyConnection(Connection connection) throws SQLException {
+
+ Connection spy = spy(connection);
+ return spy;
+ }
+
+ public static String getFilePath(String fileName) {
+
+ if (StringUtils.isNotBlank(fileName)) {
+ return Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "dbscripts", fileName)
+ .toString();
+ }
+ throw new IllegalArgumentException("DB Script file name cannot be empty.");
+ }
+
+ public static void initiateH2Base() throws Exception {
+
+ BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setDriverClassName("org.h2.Driver");
+ dataSource.setUsername("username");
+ dataSource.setPassword("password");
+ dataSource.setUrl("jdbc:h2:mem:test" + DB_NAME);
+ try (Connection connection = dataSource.getConnection()) {
+ connection.createStatement().executeUpdate("DROP ALL OBJECTS");
+ connection.createStatement().executeUpdate("RUNSCRIPT FROM '" + getFilePath(H2_SCRIPT_NAME) + "'");
+ }
+ dataSourceMap.put(DB_NAME, dataSource);
+ }
+
+ public static void closeH2Base() throws Exception {
+
+ BasicDataSource dataSource = dataSourceMap.get(DB_NAME);
+ if (dataSource != null) {
+ dataSource.close();
+ }
+ }
+
+ public static Connection getConnection() throws SQLException {
+
+ if (dataSourceMap.get(DB_NAME) != null) {
+ return dataSourceMap.get(DB_NAME).getConnection();
+ }
+ throw new RuntimeException("No data source initiated for database: " + DB_NAME);
+ }
+
+}
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/dbscripts/h2.sql b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/dbscripts/h2.sql
new file mode 100644
index 000000000000..224c8e2144ae
--- /dev/null
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/dbscripts/h2.sql
@@ -0,0 +1,49 @@
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION BOOLEAN,
+ SIGN_RESPONSE BOOLEAN NOT NULL,
+ SIGN_ASSERTIONS BOOLEAN NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION BOOLEAN,
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED BOOLEAN NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED BOOLEAN,
+ IDP_INIT_SLO_ENABLED BOOLEAN,
+ QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ECP_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN,
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT DATETIME NOT NULL,
+ UPDATED_AT DATETIME NOT NULL,
+ PRIMARY KEY (ID)
+);
+
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE
+);
+
+--SAML--
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml
index 086c07b39dae..fa65ac76205f 100644
--- a/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml
+++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml
@@ -26,6 +26,7 @@
+
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql
index b029ed8dd200..c6743bb97bea 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql
@@ -1836,6 +1836,73 @@ CREATE TABLE IDN_OAUTH_PAR (
PARAMETERS CLOB(1M)
)
/
+CREATE TABLE IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL,
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION CHAR(1),
+ SIGN_RESPONSE CHAR(1) NOT NULL,
+ SIGN_ASSERTIONS CHAR(1) NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION CHAR(1),
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED CHAR(1) NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED CHAR(1) NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED CHAR(1),
+ IDP_INIT_SLO_ENABLED CHAR(1),
+ QUERY_REQUEST_PROFILE_ENABLED CHAR(1) NOT NULL,
+ ECP_ENABLED CHAR(1) NOT NULL,
+ ARTIFACT_BINDING_ENABLED CHAR(1) NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION CHAR(1),
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT TIMESTAMP NOT NULL,
+ UPDATED_AT TIMESTAMP NOT NULL,
+ PRIMARY KEY (ID)
+)
+/
+CREATE SEQUENCE IDN_SAML2_SERVICE_PROVIDER_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
+/
+CREATE TRIGGER IDN_SAML2_SERVICE_PROVIDER_TRIG NO CASCADE
+ BEFORE INSERT
+ ON IDN_SAML2_SERVICE_PROVIDER
+ REFERENCING NEW AS NEW
+ FOR EACH ROW MODE DB2SQL
+ BEGIN ATOMIC
+ SET (NEW.ID) = (NEXTVAL FOR IDN_SAML2_SERVICE_PROVIDER_SEQ);
+ END
+/
+CREATE TABLE IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL,
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE
+)
+/
+CREATE SEQUENCE IDN_SAML2_SP_PROPERTIES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
+/
+CREATE TRIGGER IDN_SAML2_SP_PROPERTIES_TRIG NO CASCADE
+ BEFORE INSERT
+ ON IDN_SAML2_SP_PROPERTIES
+ REFERENCING NEW AS NEW
+ FOR EACH ROW MODE DB2SQL
+ BEGIN ATOMIC
+ SET (NEW.ID) = (NEXTVAL FOR IDN_SAML2_SP_PROPERTIES_SEQ);
+ END
+/
CREATE TABLE IDN_ORG_USER_INVITATION (
ID INTEGER NOT NULL,
@@ -2327,3 +2394,11 @@ CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID)
/
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID)
/
+
+--SAML--
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+/
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+/
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
+/
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql
index 56f35ea09d30..f1deb2ed35f9 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql
@@ -1220,6 +1220,51 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH_PAR (
PARAMETERS MEDIUMTEXT
);
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION BOOLEAN,
+ SIGN_RESPONSE BOOLEAN NOT NULL,
+ SIGN_ASSERTIONS BOOLEAN NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION BOOLEAN,
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED BOOLEAN NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED BOOLEAN,
+ IDP_INIT_SLO_ENABLED BOOLEAN,
+ QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ECP_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN,
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT DATETIME NOT NULL,
+ UPDATED_AT DATETIME NOT NULL,
+ PRIMARY KEY (ID)
+);
+
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE
+);
+
CREATE TABLE IF NOT EXISTS IDN_ORG_USER_INVITATION (
ID INTEGER NOT NULL AUTO_INCREMENT,
INVITATION_ID VARCHAR(40) NOT NULL,
@@ -1526,3 +1571,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID);
-- RULES --
CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID);
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID);
+
+-- SAML --
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql
index 199d5d9d2404..8b0977d4c591 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql
@@ -1355,6 +1355,53 @@ CREATE TABLE IDN_OAUTH_PAR (
PRIMARY KEY (REQ_URI_REF)
);
+IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_SAML2_SERVICE_PROVIDER]') AND TYPE IN (N'U'))
+CREATE TABLE IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL IDENTITY,
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION BIT,
+ SIGN_RESPONSE BIT NOT NULL,
+ SIGN_ASSERTIONS BIT NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION BIT,
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED BIT NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED BIT NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED BIT,
+ IDP_INIT_SLO_ENABLED BIT,
+ QUERY_REQUEST_PROFILE_ENABLED BIT NOT NULL,
+ ECP_ENABLED BIT NOT NULL,
+ ARTIFACT_BINDING_ENABLED BIT NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BIT,
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT DATETIME NOT NULL,
+ UPDATED_AT DATETIME NOT NULL,
+ PRIMARY KEY (ID)
+);
+
+IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_SAML2_SP_PROPERTIES]') AND TYPE IN (N'U'))
+CREATE TABLE IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL IDENTITY,
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE
+);
+
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_ORG_USER_INVITATION]') AND TYPE IN (N'U'))
CREATE TABLE IDN_ORG_USER_INVITATION (
ID INTEGER IDENTITY(1,1) NOT NULL,
@@ -1680,6 +1727,11 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID);
CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID);
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID);
+-- SAML --
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
+
GO
-- Trigger IDN_CLAIM delete by dialect on IDN_CLAIM_DIALECT deletion --
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql
index e53f3c0f542f..4e9e391a43c2 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql
@@ -1382,6 +1382,51 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH_PAR (
PARAMETERS MEDIUMTEXT
) ENGIN NDB;
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION BOOLEAN,
+ SIGN_RESPONSE BOOLEAN NOT NULL,
+ SIGN_ASSERTIONS BOOLEAN NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION BOOLEAN,
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED BOOLEAN NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED BOOLEAN,
+ IDP_INIT_SLO_ENABLED BOOLEAN,
+ QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ECP_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN,
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT DATETIME NOT NULL,
+ UPDATED_AT DATETIME NOT NULL,
+ PRIMARY KEY (ID)
+) ENGINE NDB;
+
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE
+) ENGINE NDB;
+
CREATE TABLE IDN_ORG_USER_INVITATION (
ID INTEGER NOT NULL AUTO_INCREMENT,
INVITATION_ID VARCHAR(40) NOT NULL,
@@ -1718,3 +1763,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID);
-- RULES --
CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID);
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID);
+
+-- SAML --
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql
index 6a1eb37a6492..b2839a229674 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql
@@ -1247,6 +1247,51 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH_PAR (
PARAMETERS MEDIUMTEXT
)DEFAULT CHARACTER SET latin1 ENGINE INNODB;
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION BOOLEAN,
+ SIGN_RESPONSE BOOLEAN NOT NULL,
+ SIGN_ASSERTIONS BOOLEAN NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION BOOLEAN,
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED BOOLEAN NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED BOOLEAN,
+ IDP_INIT_SLO_ENABLED BOOLEAN,
+ QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ECP_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN,
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT TIMESTAMP NOT NULL,
+ UPDATED_AT TIMESTAMP NOT NULL,
+ PRIMARY KEY (ID)
+) DEFAULT CHARACTER SET latin1 ENGINE INNODB;
+
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL AUTO_INCREMENT,
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE
+) DEFAULT CHARACTER SET latin1 ENGINE INNODB;
+
CREATE TABLE IDN_ORG_USER_INVITATION (
ID INTEGER NOT NULL AUTO_INCREMENT,
INVITATION_ID VARCHAR(40) NOT NULL,
@@ -1554,3 +1599,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID);
-- RULES --
CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID);
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID);
+
+-- SAML --
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql
index 9e127808dceb..019f97e114fa 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql
@@ -2016,6 +2016,73 @@ CREATE TABLE IDN_OAUTH_PAR (
PARAMETERS CLOB
)
/
+CREATE TABLE IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL,
+ ISSUER VARCHAR2(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR2(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR2(255) NOT NULL,
+ CERT_ALIAS VARCHAR2(255),
+ REQ_SIG_VALIDATION CHAR(1),
+ SIGN_RESPONSE CHAR(1) NOT NULL,
+ SIGN_ASSERTIONS CHAR(1) NOT NULL,
+ SIGNING_ALGO VARCHAR2(255) NOT NULL,
+ DIGEST_ALGO VARCHAR2(255) NOT NULL,
+ ENCRYPT_ASSERTION CHAR(1),
+ ASSERTION_ENCRYPTION_ALGO VARCHAR2(255),
+ KEY_ENCRYPTION_ALGO VARCHAR2(255),
+ ATTR_PROFILE_ENABLED CHAR(1) NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR2(255),
+ SLO_PROFILE_ENABLED CHAR(1) NOT NULL,
+ SLO_METHOD VARCHAR2(255),
+ SLO_RESPONSE_URL VARCHAR2(2048),
+ SLO_REQUEST_URL VARCHAR2(2048),
+ IDP_INIT_SSO_ENABLED CHAR(1),
+ IDP_INIT_SLO_ENABLED CHAR(1),
+ QUERY_REQUEST_PROFILE_ENABLED CHAR(1) NOT NULL,
+ ECP_ENABLED CHAR(1) NOT NULL,
+ ARTIFACT_BINDING_ENABLED CHAR(1) NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION CHAR(1),
+ IDP_ENTITY_ID_ALIAS VARCHAR2(255),
+ ISSUER_QUALIFIER VARCHAR2(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR2(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT TIMESTAMP NOT NULL,
+ UPDATED_AT TIMESTAMP NOT NULL,
+ PRIMARY KEY (ID)
+)
+/
+CREATE SEQUENCE IDN_SAML2_SERVICE_PROVIDER_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
+/
+CREATE OR REPLACE TRIGGER IDN_SAML2_SERVICE_PROVIDER_TRIG
+ BEFORE INSERT
+ ON IDN_SAML2_SERVICE_PROVIDER
+ REFERENCING NEW AS NEW
+ FOR EACH ROW
+ BEGIN
+ SELECT IDN_SAML2_SERVICE_PROVIDER_SEQ.nextval INTO :NEW.ID FROM dual;
+ END;
+/
+CREATE TABLE IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL,
+ PROPERTY_NAME VARCHAR2(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR2(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE
+)
+/
+CREATE SEQUENCE IDN_SAML2_SP_PROPERTIES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
+/
+CREATE OR REPLACE TRIGGER IDN_SAML2_SP_PROPERTIES_TRIG
+ BEFORE INSERT
+ ON IDN_SAML2_SP_PROPERTIES
+ REFERENCING NEW AS NEW
+ FOR EACH ROW
+ BEGIN
+ SELECT IDN_SAML2_SP_PROPERTIES_SEQ.nextval INTO :NEW.ID FROM dual;
+ END;
+/
CREATE TABLE IDN_ORG_USER_INVITATION (
ID INTEGER NOT NULL,
INVITATION_ID VARCHAR(40) NOT NULL,
@@ -2386,3 +2453,11 @@ CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID)
/
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID)
/
+
+-- SAML --
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+/
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+/
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
+/
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql
index 9b90807829d4..bfc0770cee94 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql
@@ -1849,6 +1849,73 @@ CREATE TABLE IDN_OAUTH_PAR (
PARAMETERS CLOB
)
/
+CREATE TABLE IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL,
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION CHAR(1),
+ SIGN_RESPONSE CHAR(1) NOT NULL,
+ SIGN_ASSERTIONS CHAR(1) NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION CHAR(1),
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED CHAR(1) NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED CHAR(1) NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED CHAR(1),
+ IDP_INIT_SLO_ENABLED CHAR(1),
+ QUERY_REQUEST_PROFILE_ENABLED CHAR(1) NOT NULL,
+ ECP_ENABLED CHAR(1) NOT NULL,
+ ARTIFACT_BINDING_ENABLED CHAR(1) NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION CHAR(1),
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT TIMESTAMP NOT NULL,
+ UPDATED_AT TIMESTAMP NOT NULL,
+ PRIMARY KEY (ID)
+)
+/
+CREATE SEQUENCE IDN_SAML2_SERVICE_PROVIDER_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
+/
+CREATE OR REPLACE TRIGGER IDN_SAML2_SERVICE_PROVIDER_TRIG
+ BEFORE INSERT
+ ON IDN_SAML2_SERVICE_PROVIDER
+ REFERENCING NEW AS NEW
+ FOR EACH ROW
+ BEGIN
+ SELECT IDN_SAML2_SERVICE_PROVIDER_SEQ.nextval INTO :NEW.ID FROM dual;
+ END;
+/
+CREATE TABLE IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL,
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE
+)
+/
+CREATE SEQUENCE IDN_SAML2_SP_PROPERTIES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE
+/
+CREATE OR REPLACE TRIGGER IDN_SAML2_SP_PROPERTIES_TRIG
+ BEFORE INSERT
+ ON IDN_SAML2_SP_PROPERTIES
+ REFERENCING NEW AS NEW
+ FOR EACH ROW
+ BEGIN
+ SELECT IDN_SAML2_SP_PROPERTIES_SEQ.nextval INTO :NEW.ID FROM dual;
+ END;
+/
CREATE TABLE IDN_ORG_USER_INVITATION (
ID INTEGER NOT NULL,
INVITATION_ID VARCHAR(40) NOT NULL,
@@ -2290,3 +2357,11 @@ CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID)
/
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID)
/
+
+-- SAML --
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+/
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+/
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
+/
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql
index 185115350c3b..7b51ab2cf7c6 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql
@@ -1455,6 +1455,57 @@ CREATE TABLE IDN_OAUTH_PAR (
PARAMETERS TEXT
);
+DROP TABLE IF EXISTS IDN_SAML2_SERVICE_PROVIDER;
+DROP SEQUENCE IF EXISTS IDN_SAML2_SP_SEQ;
+CREATE SEQUENCE IDN_SAML2_SP_SEQ;
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER (
+ ID INTEGER NOT NULL DEFAULT NEXTVAL('IDN_SAML2_SERVICE_PROVIDER_SEQ'),
+ ISSUER VARCHAR(255) NOT NULL,
+ DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL,
+ NAME_ID_FORMAT VARCHAR(255) NOT NULL,
+ CERT_ALIAS VARCHAR(255),
+ REQ_SIG_VALIDATION BOOLEAN,
+ SIGN_RESPONSE BOOLEAN NOT NULL,
+ SIGN_ASSERTIONS BOOLEAN NOT NULL,
+ SIGNING_ALGO VARCHAR(255) NOT NULL,
+ DIGEST_ALGO VARCHAR(255) NOT NULL,
+ ENCRYPT_ASSERTION BOOLEAN,
+ ASSERTION_ENCRYPTION_ALGO VARCHAR(255),
+ KEY_ENCRYPTION_ALGO VARCHAR(255),
+ ATTR_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ATTR_SERVICE_INDEX VARCHAR(255),
+ SLO_PROFILE_ENABLED BOOLEAN NOT NULL,
+ SLO_METHOD VARCHAR(255),
+ SLO_RESPONSE_URL VARCHAR(2048),
+ SLO_REQUEST_URL VARCHAR(2048),
+ IDP_INIT_SSO_ENABLED BOOLEAN,
+ IDP_INIT_SLO_ENABLED BOOLEAN,
+ QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL,
+ ECP_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL,
+ ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN,
+ IDP_ENTITY_ID_ALIAS VARCHAR(255),
+ ISSUER_QUALIFIER VARCHAR(255),
+ SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255),
+ TENANT_ID INTEGER,
+ VERSION VARCHAR(15) NOT NULL,
+ CREATED_AT TIMESTAMP NOT NULL,
+ UPDATED_AT TIMESTAMP NOT NULL,
+ PRIMARY KEY (ID)
+);
+
+DROP TABLE IF EXISTS IDN_SAML2_SP_PROPERTIES;
+DROP SEQUENCE IF EXISTS IDN_SAML2_SP_PROPERTY_SEQ;
+CREATE SEQUENCE IDN_SAML2_SP_PROPERTY_SEQ;
+CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES (
+ ID INTEGER NOT NULL DEFAULT NEXTVAL('IDN_SAML2_SP_PROPERTIES_SEQ'),
+ PROPERTY_NAME VARCHAR(255) NOT NULL,
+ PROPERTY_VALUE VARCHAR(2048) NOT NULL,
+ SP_ID INTEGER NOT NULL,
+ PRIMARY KEY (ID),
+ FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE
+);
+
DROP TABLE IF EXISTS IDN_ORG_USER_INVITATION;
DROP SEQUENCE IF EXISTS IDN_ORG_USER_INVITATION_SEQ;
CREATE SEQUENCE IDN_ORG_USER_INVITATION_SEQ;
@@ -1807,3 +1858,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID);
-- RULES --
CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID);
CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID);
+
+-- SAML --
+CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID);
+CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID);
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml
index 4578a389f1b3..5e5159bfa1c3 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml
@@ -77,7 +77,7 @@
-->
database
-
+ database
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2
index 9e5fe3ded889..e586c1a6c036 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2
@@ -87,6 +87,7 @@
{{data_storage_type.notification_templates}}
{{data_storage_type.xacml}}
+ {{data_storage_type.saml}}
diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json
index 199e02614d84..03bd28992be9 100644
--- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json
+++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json
@@ -11,6 +11,7 @@
"identity_data_source.skip_db_schema_creation": false,
"identity_data_source.skip_claim_metadata_persistence": true,
"data_storage_type.notification_templates": "database",
+ "data_storage_type.saml": "database",
"database.identity_db.pool_options.maxActive": "50",
"database.identity_db.pool_options.maxWait": "60000",
"database.identity_db.pool_options.testOnBorrow": "true",