From f1974d086f18f4946a69a29922fbfc79734c0c28 Mon Sep 17 00:00:00 2001 From: Sahan Dilshan <32576163+sahandilshan@users.noreply.github.com> Date: Tue, 12 Mar 2024 10:21:45 +0530 Subject: [PATCH] Call app-mgt component to handle inbound details (#543) * Call app-mgt component to handle inbound details * Fix NPE * bump version * Add license headers * Address comment --------- Co-authored-by: vivekvinushanth --- .../pom.xml | 5 + .../ServerApplicationManagementService.java | 98 ++++++++++++------- .../ApiModelToServiceProvider.java | 42 ++++---- .../application/InboundProtocolToDTO.java | 52 ++++++++++ .../functions/application/ModelToDTO.java | 32 ++++++ .../application/inbound/InboundFunctions.java | 20 +--- .../inbound/UpdateInboundProtocols.java | 14 +-- .../oauth2/ApiModelToOAuthConsumerApp.java | 6 +- .../inbound/oauth2/OAuthInboundFunctions.java | 52 ++++++++-- .../sts}/PassiveSTSInboundFunctions.java | 17 +++- .../saml/ApiModelToSAML2ProtocolConfig.java | 43 ++++++++ .../inbound/saml/SAMLInboundFunctions.java | 14 ++- pom.xml | 12 ++- 13 files changed, 310 insertions(+), 97 deletions(-) create mode 100644 components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/InboundProtocolToDTO.java create mode 100644 components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ModelToDTO.java rename components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/{ => passive/sts}/PassiveSTSInboundFunctions.java (86%) create mode 100644 components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/ApiModelToSAML2ProtocolConfig.java diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/pom.xml b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/pom.xml index 01c32941d6..fe1f66a880 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/pom.xml +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/pom.xml @@ -109,6 +109,11 @@ org.wso2.carbon.identity.oauth provided + + org.wso2.carbon.identity.inbound.auth.oauth2 + org.wso2.carbon.identity.oauth.common + provided + org.wso2.carbon.identity.inbound.auth.saml2 org.wso2.carbon.identity.sso.saml diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java index 9e207deef1..a6b78f48b4 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/ServerApplicationManagementService.java @@ -71,10 +71,10 @@ import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.ServiceProviderToApiModel; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.UpdateServiceProvider; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundAuthConfigToApiModel; -import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.PassiveSTSInboundFunctions; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.WSTrustInboundFunctions; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.custom.CustomInboundFunctions; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.oauth2.OAuthInboundFunctions; +import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.passive.sts.PassiveSTSInboundFunctions; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.saml.SAMLInboundFunctions; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.provisioning.BuildProvisioningConfiguration; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.provisioning.UpdateProvisioningConfiguration; @@ -107,6 +107,8 @@ import org.wso2.carbon.identity.application.mgt.ApplicationConstants; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementService; +import org.wso2.carbon.identity.application.mgt.inbound.dto.ApplicationDTO; +import org.wso2.carbon.identity.application.mgt.inbound.dto.InboundProtocolConfigurationDTO; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.configuration.mgt.core.model.ResourceSearchBean; import org.wso2.carbon.identity.configuration.mgt.core.search.ComplexCondition; @@ -151,7 +153,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -159,7 +160,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; - import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -183,7 +183,6 @@ import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundFunctions.getInboundAuthKey; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundFunctions.getInboundAuthenticationRequestConfig; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundFunctions.rollbackInbound; -import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundFunctions.rollbackInbounds; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundFunctions.updateOrInsertInbound; import static org.wso2.carbon.identity.api.server.common.Constants.ERROR_CODE_RESOURCE_LIMIT_REACHED; import static org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.Application.CONSOLE_APP; @@ -764,7 +763,8 @@ public String createApplication(ApplicationModel applicationModel, String templa /* * CORS adding step should be moved to the service layer and the validation also should happen there. - * But for now we are handling the validation here. + * But for now we are handling the validation here. (This should move when the CORS management is + * moved to the service layer). */ if (applicationModel.getInboundProtocolConfiguration() != null && applicationModel.getInboundProtocolConfiguration().getOidc() != null) { @@ -797,14 +797,14 @@ public String createApplication(ApplicationModel applicationModel, String templa String tenantDomain = ContextLoader.getTenantDomainFromContext(); String applicationId = null; - ServiceProvider application = new ApiModelToServiceProvider().apply(applicationModel); try { - applicationId = getApplicationManagementService().createApplication(application, tenantDomain, username); - + ApplicationDTO applicationDTO = new ApiModelToServiceProvider().apply(applicationModel); + applicationId = getApplicationManagementService().createApplication(applicationDTO, tenantDomain, username); + // Update owner for B2B Self Service applications. - if (application.isB2BSelfServiceApp()) { + if (applicationDTO.getServiceProvider().isB2BSelfServiceApp()) { String systemUserID = org.wso2.carbon.identity.organization.management.service.util.Utils - .getB2BSelfServiceSystemUser(tenantDomain); + .getB2BSelfServiceSystemUser(tenantDomain); if (StringUtils.isNotEmpty(systemUserID)) { ApplicationOwner systemOwner = new ApplicationOwner(); systemOwner.id(systemUserID); @@ -819,10 +819,6 @@ public String createApplication(ApplicationModel applicationModel, String templa } return applicationId; } catch (IdentityApplicationManagementException e) { - if (log.isDebugEnabled()) { - log.debug("Error while creating application. Rolling back possibly created inbound config data.", e); - } - rollbackInbounds(getConfiguredInbounds(application)); throw handleIdentityApplicationManagementException(e, "Error creating application."); } catch (CORSManagementServiceException e) { if (log.isDebugEnabled()) { @@ -841,14 +837,10 @@ public String createApplication(ApplicationModel applicationModel, String templa * For more information read https://github.com/wso2/product-is/issues/12579. This is to overcome the * above issue. */ - if (log.isDebugEnabled()) { - log.debug("Server encountered unexpected error. Rolling back created application data.", e); - } if (applicationId != null) { deleteApplication(applicationId); - } else { - rollbackInbounds(getConfiguredInbounds(application)); } + log.error(ERROR_PROCESSING_REQUEST.getDescription(), e); throw Utils.buildServerError(ERROR_PROCESSING_REQUEST.getCode(), ERROR_PROCESSING_REQUEST.getMessage(), ERROR_PROCESSING_REQUEST.getDescription()); } @@ -1056,12 +1048,12 @@ public void putInboundOAuthConfiguration(String applicationId, OpenIDConnectConf * But for now we are handling the validation here. */ validateCORSOrigins(oidcConfigModel.getAllowedOrigins()); - putInbound(applicationId, oidcConfigModel, OAuthInboundFunctions::putOAuthInbound); + putApplicationInbound(applicationId, oidcConfigModel, OAuthInboundFunctions::getInboundProtocolConfig); } public void putInboundSAMLConfiguration(String applicationId, SAML2Configuration saml2Configuration) { - putInbound(applicationId, saml2Configuration, SAMLInboundFunctions::putSAMLInbound); + putApplicationInbound(applicationId, saml2Configuration, SAMLInboundFunctions::getInboundProtocolConfig); } public void putInboundPassiveSTSConfiguration(String applicationId, @@ -1619,7 +1611,9 @@ private void deleteInbound(String applicationId, String inboundType) { .toArray(InboundAuthenticationRequestConfig[]::new); appToUpdate.getInboundAuthenticationConfig().setInboundAuthenticationRequestConfigs(filteredInbounds); - updateServiceProvider(applicationId, appToUpdate); + // We don't need to pass the inboundDTO information here since the updated inbound is already removed at + // this point and also updated in the appToUpdate object. + updateServiceProvider(applicationId, appToUpdate, null); } // Delete the associated CORS origins if the inboundType is oauth2. @@ -1659,15 +1653,6 @@ private ServiceProvider getServiceProvider(String applicationId) { return application; } - private List getConfiguredInbounds(ServiceProvider app) { - - if (app.getInboundAuthenticationConfig() != null && - app.getInboundAuthenticationConfig().getInboundAuthenticationRequestConfigs() != null) { - return Arrays.asList(app.getInboundAuthenticationConfig().getInboundAuthenticationRequestConfigs()); - } - return Collections.emptyList(); - } - private List getApplicationListItems(ApplicationBasicInfo[] allApplicationBasicInfo) { return Arrays.stream(allApplicationBasicInfo) @@ -1736,6 +1721,34 @@ private void putInbound(String applicationId, throw error; } } + + /** + * Create or replace the provided inbound configuration. + * + * @param applicationId Resource id of the app. + * @param inboundApiModel Inbound API model to be created or replaced. + * @param getInboundDTO A function that takes the inbound API model and application as input and provides the + * InboundProtocolConfigurationDTO that matches with the protocol. + */ + private void putApplicationInbound(String applicationId, I inboundApiModel, BiFunction getInboundDTO) { + + // We need a cloned copy of the Service Provider so that we changes we do not make cache dirty. + ServiceProvider application = cloneApplication(applicationId); + + // Update the service provider with the inbound configuration. + InboundProtocolConfigurationDTO inboundDTO = getInboundDTO.apply(application, inboundApiModel); + try { + // Call the app-mgt service and update the inbound auth configs and application details + updateServiceProvider(applicationId, application, inboundDTO); + } catch (APIError error) { + if (log.isDebugEnabled()) { + log.debug("Error while updating application: " + applicationId + ". The possible rollbacks will be " + + "handle from the framework level."); + } + throw error; + } + } private void doRollback(String applicationId, InboundAuthenticationRequestConfig updatedInbound) { @@ -1756,13 +1769,30 @@ private void doRollback(String applicationId, InboundAuthenticationRequestConfig } private void updateServiceProvider(String applicationId, ServiceProvider updatedApplication) { - + try { String tenantDomain = ContextLoader.getTenantDomainFromContext(); String username = ContextLoader.getUsernameFromContext(); - + + // Inbound auth config details are already added to the service provider. Therefore we don't need to pass + // the inboundDTO information here. + getApplicationManagementService().updateApplicationByResourceId( + applicationId, updatedApplication, null, tenantDomain, username); + } catch (IdentityApplicationManagementException e) { + String msg = "Error updating application with id: " + applicationId; + throw handleIdentityApplicationManagementException(e, msg); + } + } + + private void updateServiceProvider(String applicationId, ServiceProvider updatedApplication, + InboundProtocolConfigurationDTO inboundDTO) { + + try { + String tenantDomain = ContextLoader.getTenantDomainFromContext(); + String username = ContextLoader.getUsernameFromContext(); + getApplicationManagementService().updateApplicationByResourceId( - applicationId, updatedApplication, tenantDomain, username); + applicationId, updatedApplication, inboundDTO, tenantDomain, username); } catch (IdentityApplicationManagementException e) { String msg = "Error updating application with id: " + applicationId; throw handleIdentityApplicationManagementException(e, msg); diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ApiModelToServiceProvider.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ApiModelToServiceProvider.java index 8c3cd382dc..1864b59af0 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ApiModelToServiceProvider.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ApiModelToServiceProvider.java @@ -19,26 +19,26 @@ import org.wso2.carbon.identity.api.server.application.management.v1.AdvancedApplicationConfiguration; import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationModel; -import org.wso2.carbon.identity.api.server.application.management.v1.AssociatedRolesConfig; import org.wso2.carbon.identity.api.server.application.management.v1.AuthenticationSequence; import org.wso2.carbon.identity.api.server.application.management.v1.ClaimConfiguration; import org.wso2.carbon.identity.api.server.application.management.v1.InboundProtocols; import org.wso2.carbon.identity.api.server.application.management.v1.ProvisioningConfiguration; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.UpdateInboundProtocols; import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.provisioning.UpdateProvisioningConfiguration; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException; import org.wso2.carbon.identity.application.common.model.ServiceProvider; - -import java.util.function.Function; +import org.wso2.carbon.identity.application.mgt.inbound.dto.ApplicationDTO; +import org.wso2.carbon.identity.application.mgt.inbound.dto.InboundProtocolsDTO; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.Utils.setIfNotNull; /** * Converts the API model object into a ServiceProvider object. */ -public class ApiModelToServiceProvider implements Function { +public class ApiModelToServiceProvider implements ModelToDTO { @Override - public ServiceProvider apply(ApplicationModel applicationModel) { + public ApplicationDTO apply(ApplicationModel applicationModel) throws IdentityApplicationManagementClientException { ServiceProvider application = new ServiceProvider(); @@ -55,30 +55,36 @@ public ServiceProvider apply(ApplicationModel applicationModel) { addClaimConfigurationToApplication(application, applicationModel.getClaimConfiguration()); addAuthenticationSequence(application, applicationModel.getAuthenticationSequence()); addProvisioningConfiguration(application, applicationModel.getProvisioningConfigurations()); - addInboundAuthenticationProtocolsToApplication(application, applicationModel.getInboundProtocolConfiguration()); - addAssociatedRolesConfigurations(application, applicationModel.getAssociatedRoles()); - addLogoutReturnUrl(application, applicationModel.getLogoutReturnUrl()); - return application; - } - private void addLogoutReturnUrl(ServiceProvider application, String logoutReturnUrl) { + ApplicationDTO.Builder applicationDTOBuilder = new ApplicationDTO.Builder(); + applicationDTOBuilder.serviceProvider(application); - new UpdateLogoutReturnUrl().apply(application, logoutReturnUrl); + // Converting InboundProtocols to InboundProtocolsDTO and adding it to the ApplicationModel. + applicationDTOBuilder.inboundProtocolConfigurationDto( + createInboundProtocolConfiguration(application, applicationModel.getInboundProtocolConfiguration())); + // This is to add the inbound authentication protocols to the application that doesn't have inbound auth + // config handler. + addInboundAuthenticationProtocolsToApplication(application, applicationModel.getInboundProtocolConfiguration()); + return applicationDTOBuilder.build(); } - private void addAssociatedRolesConfigurations(ServiceProvider application, AssociatedRolesConfig associatedRoles) { + private void addInboundAuthenticationProtocolsToApplication(ServiceProvider application, + InboundProtocols inboundProtocolsModel) { - if (associatedRoles != null) { - new UpdateAssociatedRoles().apply(application, associatedRoles); + if (inboundProtocolsModel != null) { + new UpdateInboundProtocols().apply(application, inboundProtocolsModel); } } - private void addInboundAuthenticationProtocolsToApplication(ServiceProvider application, - InboundProtocols inboundProtocolsModel) { + private InboundProtocolsDTO createInboundProtocolConfiguration(ServiceProvider serviceProvider, + InboundProtocols inboundProtocolsModel) + throws IdentityApplicationManagementClientException { + if (inboundProtocolsModel != null) { - new UpdateInboundProtocols().apply(application, inboundProtocolsModel); + return new InboundProtocolToDTO().apply(serviceProvider, inboundProtocolsModel); } + return null; } private void addAuthenticationSequence(ServiceProvider application, AuthenticationSequence authSequenceApiModel) { diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/InboundProtocolToDTO.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/InboundProtocolToDTO.java new file mode 100644 index 0000000000..e0145b4197 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/InboundProtocolToDTO.java @@ -0,0 +1,52 @@ +/* + * 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.api.server.application.management.v1.core.functions.application; + +import org.wso2.carbon.identity.api.server.application.management.v1.InboundProtocols; +import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.UpdateInboundProtocols; +import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.oauth2.ApiModelToOAuthConsumerApp; +import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.saml.ApiModelToSAML2ProtocolConfig; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.inbound.dto.InboundProtocolsDTO; + +/** + * Converts the inbound protocols defined in the API model to the Service Provider model. + */ +public class InboundProtocolToDTO { + + public InboundProtocolsDTO apply(ServiceProvider serviceProvider, InboundProtocols inboundProtocols) + throws IdentityApplicationManagementClientException { + + InboundProtocolsDTO inboundProtocolsDTO = new InboundProtocolsDTO(); + if (inboundProtocols.getOidc() != null) { + inboundProtocolsDTO.addProtocolConfiguration(new ApiModelToOAuthConsumerApp().apply( + serviceProvider.getApplicationName(), inboundProtocols.getOidc())); + } + if (inboundProtocols.getSaml() != null) { + inboundProtocolsDTO.addProtocolConfiguration(new ApiModelToSAML2ProtocolConfig().apply( + inboundProtocols.getSaml())); + } + /* If the inbound protocol is passiveSTS, WS-Trust or custom, the inbound protocol configuration is added to + the service provider directly. The inbound protocol configuration is not added to the InboundProtocolsDTO + because we don't have separate services to handle those inbound auth configurations. */ + new UpdateInboundProtocols().apply(serviceProvider, inboundProtocols); + return inboundProtocolsDTO; + } +} diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ModelToDTO.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ModelToDTO.java new file mode 100644 index 0000000000..74fe0aefc9 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/ModelToDTO.java @@ -0,0 +1,32 @@ +/* + * 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.api.server.application.management.v1.core.functions.application; + + +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException; + +/** + * Converts the API model object into a ServiceProvider object. + * @param Model object. + * @param DTO object. + */ +public interface ModelToDTO { + + S apply(T t) throws IdentityApplicationManagementClientException; +} diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/InboundFunctions.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/InboundFunctions.java index 3f0d5b96b1..cee92535fe 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/InboundFunctions.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/InboundFunctions.java @@ -15,8 +15,6 @@ */ package org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound; -import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.oauth2.OAuthInboundFunctions; -import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.saml.SAMLInboundFunctions; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; import org.wso2.carbon.identity.application.common.model.InboundAuthenticationConfig; import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig; @@ -87,20 +85,10 @@ public static void rollbackInbounds(List cur } public static void rollbackInbound(InboundAuthenticationRequestConfig inbound) { - - switch (inbound.getInboundAuthType()) { - case FrameworkConstants.StandardInboundProtocols.SAML2: - SAMLInboundFunctions.deleteSAMLServiceProvider(inbound); - break; - case FrameworkConstants.StandardInboundProtocols.OAUTH2: - OAuthInboundFunctions.deleteOAuthInbound(inbound); - break; - case FrameworkConstants.StandardInboundProtocols.WS_TRUST: - WSTrustInboundFunctions.deleteWSTrustConfiguration(inbound); - break; - default: - // No rollbacks required for other inbounds. - break; + + // No rollbacks required for other inbounds since those are handled by the framework. + if (inbound.getInboundAuthType().equals(FrameworkConstants.StandardInboundProtocols.WS_TRUST)) { + WSTrustInboundFunctions.deleteWSTrustConfiguration(inbound); } } diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/UpdateInboundProtocols.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/UpdateInboundProtocols.java index a4859845f9..1adfe8b445 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/UpdateInboundProtocols.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/UpdateInboundProtocols.java @@ -28,11 +28,9 @@ import java.util.List; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundFunctions.rollbackInbounds; -import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.PassiveSTSInboundFunctions.createPassiveSTSInboundConfig; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.WSTrustInboundFunctions.createWsTrustInbound; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.custom.CustomInboundFunctions.createCustomInbound; -import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.oauth2.OAuthInboundFunctions.createOAuthInbound; -import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.saml.SAMLInboundFunctions.createSAMLInbound; +import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.passive.sts.PassiveSTSInboundFunctions.createPassiveSTSInboundConfig; /** * Updates the inbound authentication protocols defined by the API model in the Service Provider model. @@ -47,14 +45,8 @@ public void apply(ServiceProvider application, InboundProtocols inboundProtocols List inbounds = new ArrayList<>(); try { - if (inboundProtocols.getOidc() != null) { - inbounds.add(createOAuthInbound(application.getApplicationName(), inboundProtocols.getOidc())); - } - - if (inboundProtocols.getSaml() != null) { - inbounds.add(createSAMLInbound(application, inboundProtocols.getSaml())); - } - + // SAML2 and OAuth2 will not be handle here, it will be handled by the relevant InboundAuthConfigHandlers + // from the framework. if (inboundProtocols.getWsTrust() != null) { inbounds.add(createWsTrustInbound(inboundProtocols.getWsTrust())); } diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/ApiModelToOAuthConsumerApp.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/ApiModelToOAuthConsumerApp.java index 074640770c..f9eeac0f8d 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/ApiModelToOAuthConsumerApp.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/ApiModelToOAuthConsumerApp.java @@ -132,8 +132,10 @@ private void updateRefreshTokenConfiguration(OAuthConsumerAppDTO consumerAppDTO, } private void updateAllowedOrigins(OAuthConsumerAppDTO consumerAppDTO, List allowedOrigins) { - - // CORS are updated directly at the REST API level through the CORS Management OSGi service. + + // Setting the allowed origins since now the cors origin services will be called and handle by the Oauth2 + // Inbound config handler + consumerAppDTO.setAllowedOrigins(allowedOrigins); } private void updateAccessTokenConfiguration(OAuthConsumerAppDTO consumerAppDTO, diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/OAuthInboundFunctions.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/OAuthInboundFunctions.java index 27278b3bf4..e87ab6783c 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/OAuthInboundFunctions.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/oauth2/OAuthInboundFunctions.java @@ -16,19 +16,19 @@ package org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.oauth2; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.api.server.application.management.common.ApplicationManagementServiceHolder; import org.wso2.carbon.identity.api.server.application.management.v1.OpenIDConnectConfiguration; -import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound - .InboundFunctions; import org.wso2.carbon.identity.api.server.common.ContextLoader; import org.wso2.carbon.identity.api.server.common.error.APIError; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.StandardInboundProtocols; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig; import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.inbound.InboundFunctions; +import org.wso2.carbon.identity.application.mgt.inbound.dto.InboundProtocolConfigurationDTO; import org.wso2.carbon.identity.cors.mgt.core.exception.CORSManagementServiceClientException; import org.wso2.carbon.identity.cors.mgt.core.exception.CORSManagementServiceException; import org.wso2.carbon.identity.cors.mgt.core.model.CORSOrigin; @@ -38,6 +38,7 @@ import org.wso2.carbon.identity.oauth.dto.OAuthConsumerAppDTO; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; @@ -55,7 +56,17 @@ public class OAuthInboundFunctions { private OAuthInboundFunctions() { } - + + /** + * This method used to create or update OAuth inbound authentication request config by calling the AuthAdminService. + * Using this method is not recommended since framework will handle the update of OAuth inbound authentication + * configurations. + * + * @param application Service provider + * @param oidcConfigModel OpenIDConnectConfiguration. + * @return InboundAuthenticationRequestConfig. + */ + @Deprecated public static InboundAuthenticationRequestConfig putOAuthInbound(ServiceProvider application, OpenIDConnectConfiguration oidcConfigModel) { @@ -64,7 +75,7 @@ public static InboundAuthenticationRequestConfig putOAuthInbound(ServiceProvider // First we identify whether this is a insert or update. try { - String currentClientId = InboundFunctions.getInboundAuthKey(application, StandardInboundProtocols.OAUTH2); + Optional optionalInboundAuthKey = InboundFunctions.getInboundAuthKey(application, OAUTH2); // Retrieve the existing CORS origins for the application. existingCORSOrigins = ApplicationManagementServiceHolder.getCorsManagementService() @@ -76,10 +87,10 @@ public static InboundAuthenticationRequestConfig putOAuthInbound(ServiceProvider ApplicationManagementServiceHolder.getCorsManagementService() .setCORSOrigins(application.getApplicationResourceId(), corsOrigins, tenantDomain); - if (currentClientId != null) { + if (optionalInboundAuthKey.isPresent()) { // Update an existing application. OAuthConsumerAppDTO oauthApp = ApplicationManagementServiceHolder.getOAuthAdminService - ().getOAuthApplicationData(currentClientId); + ().getOAuthApplicationData(optionalInboundAuthKey.get()); if (!StringUtils.equals(oauthApp.getOauthConsumerKey(), oidcConfigModel.getClientId())) { throw buildBadRequestError("Invalid ClientID provided for update."); @@ -111,13 +122,25 @@ public static InboundAuthenticationRequestConfig putOAuthInbound(ServiceProvider } catch (CORSManagementServiceException corsManagementServiceException) { throw handleException(e); } - throw handleException(e); } catch (CORSManagementServiceException e) { throw handleException(e); } } - + + /** + * Get the InboundProtocolConfigurationDTO from the OpenIDConnectConfiguration. + * + * @param application Service provider. + * @param oidcConfigModel OpenIDConnectConfiguration. + * @return InboundProtocolConfigurationDTO. + */ + public static InboundProtocolConfigurationDTO getInboundProtocolConfig( + ServiceProvider application, OpenIDConnectConfiguration oidcConfigModel) { + + return new ApiModelToOAuthConsumerApp().apply(application.getApplicationName(), oidcConfigModel); + } + private static APIError handleException(Exception e) { String message = "Error while updating OpenIDConnect configuration. " + e.getMessage(); @@ -140,7 +163,16 @@ public static InboundAuthenticationRequestConfig createOAuthInbound(OpenIDConnec return createOAuthInbound(UUID.randomUUID().toString(), oidcModel); } - + + /** + * Create OAuth inbound authentication request config by calling the AuthAdminService. It's not recommended to use + * this method since framework will handle the creation of OAuth inbound authentication configurations. + * + * @param appName Name of the application. + * @param oidcModel OpenIDConnectConfiguration. + * @return InboundAuthenticationRequestConfig. + */ + @Deprecated public static InboundAuthenticationRequestConfig createOAuthInbound(String appName, OpenIDConnectConfiguration oidcModel) { diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/PassiveSTSInboundFunctions.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/passive/sts/PassiveSTSInboundFunctions.java similarity index 86% rename from components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/PassiveSTSInboundFunctions.java rename to components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/passive/sts/PassiveSTSInboundFunctions.java index b42988b86d..d7f8345569 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/PassiveSTSInboundFunctions.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/passive/sts/PassiveSTSInboundFunctions.java @@ -13,16 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound; +package org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.passive.sts; import org.apache.commons.lang.StringUtils; import org.wso2.carbon.identity.api.server.application.management.v1.PassiveStsConfiguration; +import org.wso2.carbon.identity.api.server.application.management.v1.core.functions.application.inbound.InboundFunctions; import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.StandardInboundProtocols; import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig; import org.wso2.carbon.identity.application.common.model.Property; import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; +import java.util.HashMap; +import java.util.Map; + import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.Utils.arrayToStream; import static org.wso2.carbon.identity.api.server.application.management.v1.core.functions.Utils.buildBadRequestError; import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.PassiveSTS.PASSIVE_STS_REPLY_URL; @@ -72,7 +76,7 @@ public static InboundAuthenticationRequestConfig createPassiveSTSInboundConfig(P } else { passiveStsInbound.setProperties(new Property[]{passiveStsReplyUrl}); } - + passiveStsInbound.setData(buildPassiveSTSData(config)); return passiveStsInbound; } @@ -91,4 +95,13 @@ public static PassiveStsConfiguration getPassiveSTSConfiguration(InboundAuthenti return new PassiveStsConfiguration().realm(inboundAuth.getInboundAuthKey()).replyTo(replyTo) .replyToLogout(replyToLogout); } + + private static Map buildPassiveSTSData(PassiveStsConfiguration passiveSTSConfig) { + + Map passiveSTSData = new HashMap<>(); + passiveSTSData.put("realm", passiveSTSConfig.getRealm()); + passiveSTSData.put("replyTo", passiveSTSConfig.getReplyTo()); + passiveSTSData.put("replyToLogout", passiveSTSConfig.getReplyToLogout()); + return passiveSTSData; + } } diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/ApiModelToSAML2ProtocolConfig.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/ApiModelToSAML2ProtocolConfig.java new file mode 100644 index 0000000000..3e1a4a93c1 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/ApiModelToSAML2ProtocolConfig.java @@ -0,0 +1,43 @@ +/* + * 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.api.server.application.management.v1.core.functions.application.inbound.saml; + +import org.wso2.carbon.identity.api.server.application.management.v1.SAML2Configuration; +import org.wso2.carbon.identity.sso.saml.dto.SAML2ProtocolConfigDTO; + +import java.util.function.Function; + +/** + * Converts the SAML2Configuration model to the SAML2ProtocolConfigDTO model. + */ +public class ApiModelToSAML2ProtocolConfig implements Function { + + @Override + public SAML2ProtocolConfigDTO apply(SAML2Configuration saml2Configuration) { + + SAML2ProtocolConfigDTO saml2ProtocolConfigDTO = new SAML2ProtocolConfigDTO(); + saml2ProtocolConfigDTO.setMetadataFile(saml2Configuration.getMetadataFile()); + saml2ProtocolConfigDTO.setMetadataURL(saml2Configuration.getMetadataURL()); + if (saml2Configuration.getManualConfiguration() != null) { + saml2ProtocolConfigDTO.setManualConfiguration(new ApiModelToSAMLSSOServiceProvider().apply( + saml2Configuration.getManualConfiguration())); + } + return saml2ProtocolConfigDTO; + } +} diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/SAMLInboundFunctions.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/SAMLInboundFunctions.java index d57cfa4cda..4a1fb0bd60 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/SAMLInboundFunctions.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/java/org/wso2/carbon/identity/api/server/application/management/v1/core/functions/application/inbound/saml/SAMLInboundFunctions.java @@ -31,6 +31,7 @@ import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig; import org.wso2.carbon.identity.application.common.model.Property; import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.inbound.dto.InboundProtocolConfigurationDTO; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.sso.saml.SAMLSSOConfigServiceImpl; @@ -73,6 +74,17 @@ public static InboundAuthenticationRequestConfig putSAMLInbound(ServiceProvider } return createSAMLInbound(application, saml2Configuration); } + + public static InboundProtocolConfigurationDTO getInboundProtocolConfig( + ServiceProvider application, SAML2Configuration saml2Configuration) { + + try { + validateSingleSignOnProfileBindings(saml2Configuration); + } catch (IdentityException e) { + throw handleException(e); + } + return new ApiModelToSAML2ProtocolConfig().apply(saml2Configuration); + } /** * Validate whether the request is trying to disable either HTTP_POST or HTTP_REDIRECT or both. @@ -81,7 +93,7 @@ public static InboundAuthenticationRequestConfig putSAMLInbound(ServiceProvider * @throws IdentitySAML2ClientException If the request is trying to disable either HTTP_POST or HTTP_REDIRECT * or both. */ - private static void validateSingleSignOnProfileBindings(SAML2Configuration saml2Configuration) throws + public static void validateSingleSignOnProfileBindings(SAML2Configuration saml2Configuration) throws IdentitySAML2ClientException { if (saml2Configuration.getManualConfiguration() == null) { diff --git a/pom.xml b/pom.xml index fbcd6cde3b..5313cb0a13 100644 --- a/pom.xml +++ b/pom.xml @@ -310,6 +310,12 @@ ${identity.inbound.saml2.version} provided + + org.wso2.carbon.identity.inbound.auth.oauth2 + org.wso2.carbon.identity.oauth.common + ${identity.inbound.oauth2.version} + provided + org.wso2.carbon.identity.framework org.wso2.carbon.identity.user.store.configuration @@ -779,13 +785,13 @@ 1.4 1.2.4 1.8.62 - 5.25.609 + 7.0.50 3.0.5 1.12.0 **/gen/**/* 1.8.7 - 6.11.188 - 5.11.16 + 7.0.15 + 5.11.38 1.9.4 findbugs-exclude-filter.xml 4.9.17