diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/pom.xml b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/pom.xml index b8e28c7cfd..d7d46402a2 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/pom.xml +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/pom.xml @@ -81,5 +81,10 @@ org.wso2.carbon.identity.auth.attribute.handler provided + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.api.resource.mgt + provided + diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementConstants.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementConstants.java index 5de79a136f..3865722114 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementConstants.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementConstants.java @@ -51,6 +51,8 @@ private ApplicationManagementConstants() { public static final String NAME = "name"; public static final String CLIENT_ID = "clientId"; public static final String ISSUER = "issuer"; + public static final String RBAC = "RBAC"; + public static final String NO_POLICY = "NO POLICY"; public static final String NON_EXISTING_USER_CODE = "30007 - "; @@ -102,6 +104,21 @@ public enum ErrorMessage { USE_EXTERNAL_CONSENT_PAGE_NOT_SUPPORTED("60506", "Unsupported application property.", "'useExternalConsentPage' is not yet supported for SAML applications in this version of the API."), + API_RESOURCE_NOT_FOUND("60507", + "API resource not found.", + "API resource with id: %s is not found in the tenant domain: %s."), + SCOPES_NOT_FOUND("60508", + "API scopes not found.", + "One or more scopes in the request is not found for the API resource with Id: %s in the " + + "tenant domain: %s."), + API_RESOURCE_ALREADY_AUTHORIZED("60509", "API resource already authorized.", + "API resource with id: %s is already authorized for the application with id: %s."), + AUTHORIZED_API_NOT_FOUND("60510", "API resource not authorized for the application.", + "API resource with id: %s is not authorized for the application with id: %s."), + INVALID_POLICY_VALUE("60511", "Invalid policy id value provided.", + "Invalid policy id value. It should be 'RBAC' or 'No Policy'."), + INVALID_POLICY_TYPE_FOR_API_RESOURCE("60512", "Invalid policy type provided for the API " + + "resource.", "API resource with id: %s doesn't allow the provided policy type: %s."), // Server Errors. ERROR_RETRIEVING_SAML_METADATA("65001", diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementServiceHolder.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementServiceHolder.java index 16628ebaeb..d7acd8d19c 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementServiceHolder.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/ApplicationManagementServiceHolder.java @@ -15,7 +15,9 @@ */ package org.wso2.carbon.identity.api.server.application.management.common; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceManager; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementService; import org.wso2.carbon.identity.cors.mgt.core.CORSManagementService; import org.wso2.carbon.identity.oauth.OAuthAdminServiceImpl; import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; @@ -37,6 +39,8 @@ public class ApplicationManagementServiceHolder { private static TemplateManager templateManager; private static CORSManagementService corsManagementService; private static RealmService realmService; + private static APIResourceManager apiResourceManager; + private static AuthorizedAPIManagementService authorizedAPIManagementService; public static ApplicationManagementService getApplicationManagementService() { @@ -127,4 +131,45 @@ public static void setRealmService(RealmService realmService) { ApplicationManagementServiceHolder.realmService = realmService; } + + /** + * Get APIResourceManager. + * + * @return APIResourceManager. + */ + public static APIResourceManager getApiResourceManager() { + + return apiResourceManager; + } + + /** + * Set APIResourceManager. + * + * @param apiResourceManager APIResourceManager. + */ + public static void setApiResourceManager(APIResourceManager apiResourceManager) { + + ApplicationManagementServiceHolder.apiResourceManager = apiResourceManager; + } + + /** + * Get AuthorizedAPIManagementService. + * + * @return AuthorizedAPIManagementService. + */ + public static AuthorizedAPIManagementService getAuthorizedAPIManagementService() { + + return authorizedAPIManagementService; + } + + /** + * Set AuthorizedAPIManagementService. + * + * @param authorizedAPIManagementService AuthorizedAPIManagementService. + */ + public static void setAuthorizedAPIManagementService(AuthorizedAPIManagementService + authorizedAPIManagementService) { + + ApplicationManagementServiceHolder.authorizedAPIManagementService = authorizedAPIManagementService; + } } diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/factory/APIResourceMgtOSGiServiceFactory.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/factory/APIResourceMgtOSGiServiceFactory.java new file mode 100644 index 0000000000..d56aac2dfa --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/factory/APIResourceMgtOSGiServiceFactory.java @@ -0,0 +1,50 @@ +/* + * 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.api.server.application.management.common.factory; + +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceManager; + +/** + * Factory class for APIResourceManagementOSGiService. + */ +public class APIResourceMgtOSGiServiceFactory extends AbstractFactoryBean { + + private APIResourceManager apiResourceManager; + + @Override + public Class getObjectType() { + + return Object.class; + } + + @Override + protected APIResourceManager createInstance() throws Exception { + + if (this.apiResourceManager == null) { + apiResourceManager = (APIResourceManager) PrivilegedCarbonContext. + getThreadLocalCarbonContext().getOSGiService(APIResourceManager.class, null); + if (apiResourceManager == null) { + throw new Exception("Unable to retrieve APIResourceManager service."); + } + } + return this.apiResourceManager; + } +} diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/factory/AuthorizedAPIMgtOSGiServiceFactory.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/factory/AuthorizedAPIMgtOSGiServiceFactory.java new file mode 100644 index 0000000000..3021870d79 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.common/src/main/java/org/wso2/carbon/identity/api/server/application/management/common/factory/AuthorizedAPIMgtOSGiServiceFactory.java @@ -0,0 +1,52 @@ +/* + * 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.api.server.application.management.common.factory; + +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementService; + +/** + * Factory Beans serves as a factory for creating other beans within the IOC container. This factory bean is used to + * instantiate the AuthorizedAPIManagementService type of object inside the container. + */ +public class AuthorizedAPIMgtOSGiServiceFactory extends AbstractFactoryBean { + + private AuthorizedAPIManagementService authorizedAPIManagementService; + + @Override + public Class getObjectType() { + + return Object.class; + } + + @Override + protected AuthorizedAPIManagementService createInstance() throws Exception { + + if (this.authorizedAPIManagementService == null) { + authorizedAPIManagementService = (AuthorizedAPIManagementService) + PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getOSGiService(AuthorizedAPIManagementService.class, null); + if (authorizedAPIManagementService == null) { + throw new Exception("Unable to retrieve AuthorizedAPIManagement service."); + } + } + return this.authorizedAPIManagementService; + } +} 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 2aff4ef9a0..69c3704758 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 @@ -129,6 +129,11 @@ org.wso2.carbon.identity.core provided + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.api.resource.mgt + provided + org.wso2.carbon.identity.server.api diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApi.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApi.java index 0cf8a91191..ba2408d4b8 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApi.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApi.java @@ -34,6 +34,9 @@ import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationTemplateModel; import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationTemplatesList; import org.wso2.carbon.identity.api.server.application.management.v1.AuthProtocolMetadata; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPICreationModel; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPIPatchModel; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPIResponse; import org.wso2.carbon.identity.api.server.application.management.v1.ConfiguredAuthenticatorsModal; import org.wso2.carbon.identity.api.server.application.management.v1.CustomInboundProtocolConfiguration; import org.wso2.carbon.identity.api.server.application.management.v1.CustomInboundProtocolMetaData; @@ -68,6 +71,30 @@ public class ApplicationsApi { @Autowired private ApplicationsApiService delegate; + @Valid + @POST + @Path("/{applicationId}/authorized-apis") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Authorized an API to the application ", notes = "This API provides the capability to authorized an API to the application.
Permission required:
* /permission/admin/manage/identity/applicationmgt/create
Scope required:
* internal_application_mgt_create ", response = Void.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "Authorized APIs", }) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created", response = Void.class), + @ApiResponse(code = 400, message = "Bad Request", response = Error.class), + @ApiResponse(code = 401, message = "Unauthorized", response = Void.class), + @ApiResponse(code = 403, message = "Forbidden", response = Void.class), + @ApiResponse(code = 404, message = "Not Found", response = Void.class), + @ApiResponse(code = 500, message = "Server Error", response = Error.class) + }) + public Response addAuthorizedAPI(@ApiParam(value = "ID of the application.",required=true) @PathParam("applicationId") String applicationId, @ApiParam(value = "" ) @Valid AuthorizedAPICreationModel authorizedAPICreationModel) { + + return delegate.addAuthorizedAPI(applicationId, authorizedAPICreationModel ); + } + @Valid @PUT @Path("/{applicationId}/owner") @@ -190,6 +217,28 @@ public Response deleteApplicationTemplate(@ApiParam(value = "Application templat return delegate.deleteApplicationTemplate(templateId ); } + @Valid + @DELETE + @Path("/{applicationId}/authorized-apis/{apiId}") + + @Produces({ "application/json" }) + @ApiOperation(value = "Remove API authorization from the application ", notes = "This API provides the capability to delete an authorized API of the application.
Permission required:
* /permission/admin/manage/identity/applicationmgt/delete
Scope required:
* internal_application_mgt_delete ", response = Void.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "Authorized APIs", }) + @ApiResponses(value = { + @ApiResponse(code = 204, message = "No Content", response = Void.class), + @ApiResponse(code = 401, message = "Unauthorized", response = Void.class), + @ApiResponse(code = 403, message = "Forbidden", response = Void.class), + @ApiResponse(code = 500, message = "Server Error", response = Error.class) + }) + public Response deleteAuthorizedAPI(@ApiParam(value = "ID of the application.",required=true) @PathParam("applicationId") String applicationId, @ApiParam(value = "ID of the API resource.",required=true) @PathParam("apiId") String apiId) { + + return delegate.deleteAuthorizedAPI(applicationId, apiId ); + } + @Valid @DELETE @Path("/{applicationId}/inbound-protocols/{inboundProtocolId}") @@ -482,6 +531,29 @@ public Response getApplicationTemplate(@ApiParam(value = "Application template I return delegate.getApplicationTemplate(templateId ); } + @Valid + @GET + @Path("/{applicationId}/authorized-apis") + + @Produces({ "application/json" }) + @ApiOperation(value = "Get authorized APIs of the application. ", notes = "This API provides the capability to retrieve all the authorized APIs of the application.
Permission required:
* /permission/admin/manage/identity/applicationmgt/view
Scope required:
* internal_application_mgt_view ", response = AuthorizedAPIResponse.class, responseContainer = "List", authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "Authorized APIs", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK", response = AuthorizedAPIResponse.class, responseContainer = "List"), + @ApiResponse(code = 401, message = "Unauthorized", response = Void.class), + @ApiResponse(code = 403, message = "Forbidden", response = Void.class), + @ApiResponse(code = 404, message = "Not Found", response = Void.class), + @ApiResponse(code = 500, message = "Server Error", response = Error.class) + }) + public Response getAuthorizedAPIs(@ApiParam(value = "ID of the application.",required=true) @PathParam("applicationId") String applicationId) { + + return delegate.getAuthorizedAPIs(applicationId ); + } + @Valid @GET @Path("/{applicationId}/authenticators") @@ -862,6 +934,30 @@ public Response patchApplication(@ApiParam(value = "ID of the application.",requ return delegate.patchApplication(applicationId, applicationPatchModel ); } + @Valid + @PATCH + @Path("/{applicationId}/authorized-apis/{apiId}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Update authorized API scopes ", notes = "This API provides the capability to update an authorized API of the application.
Permission required:
* /permission/admin/manage/identity/applicationmgt/update
Scope required:
* internal_application_mgt_update ", response = Void.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "Authorized APIs", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK", response = Void.class), + @ApiResponse(code = 400, message = "Bad Request", response = Error.class), + @ApiResponse(code = 401, message = "Unauthorized", response = Void.class), + @ApiResponse(code = 403, message = "Forbidden", response = Void.class), + @ApiResponse(code = 404, message = "Not Found", response = Void.class), + @ApiResponse(code = 500, message = "Server Error", response = Error.class) + }) + public Response patchAuthorizedAPI(@ApiParam(value = "ID of the application.",required=true) @PathParam("applicationId") String applicationId, @ApiParam(value = "ID of the API resource.",required=true) @PathParam("apiId") String apiId, @ApiParam(value = "" ) @Valid AuthorizedAPIPatchModel authorizedAPIPatchModel) { + + return delegate.patchAuthorizedAPI(applicationId, apiId, authorizedAPIPatchModel ); + } + @Valid @POST @Path("/{applicationId}/inbound-protocols/oidc/regenerate-secret") diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApiService.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApiService.java index 46d2d8f59d..a98f9c8576 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApiService.java +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/ApplicationsApiService.java @@ -23,6 +23,7 @@ import org.wso2.carbon.identity.api.server.application.management.v1.*; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Multipart; + import java.io.InputStream; import java.util.List; import org.wso2.carbon.identity.api.server.application.management.v1.AdaptiveAuthTemplates; @@ -55,6 +56,8 @@ public interface ApplicationsApiService { + public Response addAuthorizedAPI(String applicationId, AuthorizedAPICreationModel authorizedAPICreationModel); + public Response changeApplicationOwner(String applicationId, ApplicationOwner applicationOwner); public Response createApplication(ApplicationModel applicationModel, String template); @@ -65,6 +68,8 @@ public interface ApplicationsApiService { public Response deleteApplicationTemplate(String templateId); + public Response deleteAuthorizedAPI(String applicationId, String apiId); + public Response deleteCustomInboundConfiguration(String applicationId, String inboundProtocolId); public Response deleteInboundOAuthConfiguration(String applicationId); @@ -89,6 +94,8 @@ public interface ApplicationsApiService { public Response getApplicationTemplate(String templateId); + public Response getAuthorizedAPIs(String applicationId); + public Response getConfiguredAuthenticators(String applicationId); public Response getCustomInboundConfiguration(String applicationId, String inboundProtocolId); @@ -121,6 +128,8 @@ public interface ApplicationsApiService { public Response patchApplication(String applicationId, ApplicationPatchModel applicationPatchModel); + public Response patchAuthorizedAPI(String applicationId, String apiId, AuthorizedAPIPatchModel authorizedAPIPatchModel); + public Response regenerateOAuthClientSecret(String applicationId); public Response revokeOAuthClient(String applicationId); diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPICreationModel.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPICreationModel.java new file mode 100644 index 0000000000..f536b29b7a --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPICreationModel.java @@ -0,0 +1,151 @@ +/* + * 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.api.server.application.management.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class AuthorizedAPICreationModel { + + private String id; + private String policyIdentifier; + private List scopes = null; + + + /** + **/ + public AuthorizedAPICreationModel id(String id) { + + this.id = id; + return this; + } + + @ApiModelProperty(example = "012df-232gf-545fg-dff23", value = "") + @JsonProperty("id") + @Valid + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + /** + **/ + public AuthorizedAPICreationModel policyIdentifier(String policyIdentifier) { + + this.policyIdentifier = policyIdentifier; + return this; + } + + @ApiModelProperty(example = "RBAC", value = "") + @JsonProperty("policyIdentifier") + @Valid + public String getPolicyIdentifier() { + return policyIdentifier; + } + public void setPolicyIdentifier(String policyIdentifier) { + this.policyIdentifier = policyIdentifier; + } + + /** + **/ + public AuthorizedAPICreationModel scopes(List scopes) { + + this.scopes = scopes; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("scopes") + @Valid + public List getScopes() { + return scopes; + } + public void setScopes(List scopes) { + this.scopes = scopes; + } + + public AuthorizedAPICreationModel addScopesItem(String scopesItem) { + if (this.scopes == null) { + this.scopes = new ArrayList<>(); + } + this.scopes.add(scopesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuthorizedAPICreationModel authorizedAPICreationModel = (AuthorizedAPICreationModel) o; + return Objects.equals(this.id, authorizedAPICreationModel.id) && + Objects.equals(this.policyIdentifier, authorizedAPICreationModel.policyIdentifier) && + Objects.equals(this.scopes, authorizedAPICreationModel.scopes); + } + + @Override + public int hashCode() { + return Objects.hash(id, policyIdentifier, scopes); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AuthorizedAPICreationModel {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" policyIdentifier: ").append(toIndentedString(policyIdentifier)).append("\n"); + sb.append(" scopes: ").append(toIndentedString(scopes)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPIPatchModel.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPIPatchModel.java new file mode 100644 index 0000000000..5833456fb2 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPIPatchModel.java @@ -0,0 +1,139 @@ +/* + * 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.api.server.application.management.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class AuthorizedAPIPatchModel { + + private List addedScopes = null; + + private List removedScopes = null; + + + /** + **/ + public AuthorizedAPIPatchModel addedScopes(List addedScopes) { + + this.addedScopes = addedScopes; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("addedScopes") + @Valid + public List getAddedScopes() { + return addedScopes; + } + public void setAddedScopes(List addedScopes) { + this.addedScopes = addedScopes; + } + + public AuthorizedAPIPatchModel addAddedScopesItem(String addedScopesItem) { + if (this.addedScopes == null) { + this.addedScopes = new ArrayList<>(); + } + this.addedScopes.add(addedScopesItem); + return this; + } + + /** + **/ + public AuthorizedAPIPatchModel removedScopes(List removedScopes) { + + this.removedScopes = removedScopes; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("removedScopes") + @Valid + public List getRemovedScopes() { + return removedScopes; + } + public void setRemovedScopes(List removedScopes) { + this.removedScopes = removedScopes; + } + + public AuthorizedAPIPatchModel addRemovedScopesItem(String removedScopesItem) { + if (this.removedScopes == null) { + this.removedScopes = new ArrayList<>(); + } + this.removedScopes.add(removedScopesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuthorizedAPIPatchModel authorizedAPIPatchModel = (AuthorizedAPIPatchModel) o; + return Objects.equals(this.addedScopes, authorizedAPIPatchModel.addedScopes) && + Objects.equals(this.removedScopes, authorizedAPIPatchModel.removedScopes); + } + + @Override + public int hashCode() { + return Objects.hash(addedScopes, removedScopes); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AuthorizedAPIPatchModel {\n"); + + sb.append(" addedScopes: ").append(toIndentedString(addedScopes)).append("\n"); + sb.append(" removedScopes: ").append(toIndentedString(removedScopes)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPIResponse.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPIResponse.java new file mode 100644 index 0000000000..5d9d1ad3d7 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedAPIResponse.java @@ -0,0 +1,194 @@ +/* + * 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.api.server.application.management.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedScope; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class AuthorizedAPIResponse { + + private String id; + private String identifier; + private String displayName; + private String policyId; + private List authorizedScopes = null; + + + /** + **/ + public AuthorizedAPIResponse id(String id) { + + this.id = id; + return this; + } + + @ApiModelProperty(example = "012df-232gf-545fg-dff23", value = "") + @JsonProperty("id") + @Valid + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + /** + **/ + public AuthorizedAPIResponse identifier(String identifier) { + + this.identifier = identifier; + return this; + } + + @ApiModelProperty(example = "https://greetings.io/v1/greet", value = "") + @JsonProperty("identifier") + @Valid + public String getIdentifier() { + return identifier; + } + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + **/ + public AuthorizedAPIResponse displayName(String displayName) { + + this.displayName = displayName; + return this; + } + + @ApiModelProperty(example = "Greetings API", value = "") + @JsonProperty("displayName") + @Valid + public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + **/ + public AuthorizedAPIResponse policyId(String policyId) { + + this.policyId = policyId; + return this; + } + + @ApiModelProperty(example = "RBAC", value = "") + @JsonProperty("policyId") + @Valid + public String getPolicyId() { + return policyId; + } + public void setPolicyId(String policyId) { + this.policyId = policyId; + } + + /** + **/ + public AuthorizedAPIResponse authorizedScopes(List authorizedScopes) { + + this.authorizedScopes = authorizedScopes; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("authorizedScopes") + @Valid + public List getAuthorizedScopes() { + return authorizedScopes; + } + public void setAuthorizedScopes(List authorizedScopes) { + this.authorizedScopes = authorizedScopes; + } + + public AuthorizedAPIResponse addAuthorizedScopesItem(AuthorizedScope authorizedScopesItem) { + if (this.authorizedScopes == null) { + this.authorizedScopes = new ArrayList<>(); + } + this.authorizedScopes.add(authorizedScopesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuthorizedAPIResponse authorizedAPIResponse = (AuthorizedAPIResponse) o; + return Objects.equals(this.id, authorizedAPIResponse.id) && + Objects.equals(this.identifier, authorizedAPIResponse.identifier) && + Objects.equals(this.displayName, authorizedAPIResponse.displayName) && + Objects.equals(this.policyId, authorizedAPIResponse.policyId) && + Objects.equals(this.authorizedScopes, authorizedAPIResponse.authorizedScopes); + } + + @Override + public int hashCode() { + return Objects.hash(id, identifier, displayName, policyId, authorizedScopes); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AuthorizedAPIResponse {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); + sb.append(" displayName: ").append(toIndentedString(displayName)).append("\n"); + sb.append(" policyId: ").append(toIndentedString(policyId)).append("\n"); + sb.append(" authorizedScopes: ").append(toIndentedString(authorizedScopes)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedScope.java b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedScope.java new file mode 100644 index 0000000000..67a8b50e27 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/application/management/v1/AuthorizedScope.java @@ -0,0 +1,140 @@ +/* + * 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.api.server.application.management.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class AuthorizedScope { + + private String id; + private String name; + private String displayName; + + /** + **/ + public AuthorizedScope id(String id) { + + this.id = id; + return this; + } + + @ApiModelProperty(example = "012df-232gf-545fg-dff23", value = "") + @JsonProperty("id") + @Valid + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + /** + **/ + public AuthorizedScope name(String name) { + + this.name = name; + return this; + } + + @ApiModelProperty(example = "bookings:read", value = "") + @JsonProperty("name") + @Valid + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + /** + **/ + public AuthorizedScope displayName(String displayName) { + + this.displayName = displayName; + return this; + } + + @ApiModelProperty(example = "Read Bookings", value = "") + @JsonProperty("displayName") + @Valid + public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuthorizedScope authorizedScope = (AuthorizedScope) o; + return Objects.equals(this.id, authorizedScope.id) && + Objects.equals(this.name, authorizedScope.name) && + Objects.equals(this.displayName, authorizedScope.displayName); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, displayName); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AuthorizedScope {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" displayName: ").append(toIndentedString(displayName)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + 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 2d21cc0176..07d7501192 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 @@ -32,7 +32,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ByteArrayResource; import org.springframework.http.MediaType; +import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceMgtException; import org.wso2.carbon.identity.api.server.application.management.common.ApplicationManagementConstants; import org.wso2.carbon.identity.api.server.application.management.common.ApplicationManagementConstants.ErrorMessage; import org.wso2.carbon.identity.api.server.application.management.common.ApplicationManagementServiceHolder; @@ -46,6 +48,10 @@ import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationTemplatesList; import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationTemplatesListItem; import org.wso2.carbon.identity.api.server.application.management.v1.AuthProtocolMetadata; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPICreationModel; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPIPatchModel; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPIResponse; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedScope; import org.wso2.carbon.identity.api.server.application.management.v1.ConfiguredAuthenticator; import org.wso2.carbon.identity.api.server.application.management.v1.ConfiguredAuthenticatorsModal; import org.wso2.carbon.identity.api.server.application.management.v1.CustomInboundProtocolConfiguration; @@ -81,8 +87,10 @@ import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.StandardInboundProtocols; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.APIResource; import org.wso2.carbon.identity.application.common.model.ApplicationBasicInfo; import org.wso2.carbon.identity.application.common.model.AuthenticationStep; +import org.wso2.carbon.identity.application.common.model.AuthorizedAPI; import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig; import org.wso2.carbon.identity.application.common.model.IdentityProvider; import org.wso2.carbon.identity.application.common.model.ImportResponse; @@ -90,11 +98,13 @@ import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig; import org.wso2.carbon.identity.application.common.model.InboundConfigurationProtocol; import org.wso2.carbon.identity.application.common.model.LocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.Scope; import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.application.common.model.SpFileContent; import org.wso2.carbon.identity.application.common.model.User; 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.base.IdentityException; import org.wso2.carbon.identity.configuration.mgt.core.model.ResourceSearchBean; import org.wso2.carbon.identity.configuration.mgt.core.search.ComplexCondition; @@ -1297,6 +1307,192 @@ public void changeApplicationOwner(String applicationId, ApplicationOwner applic updateServiceProvider(applicationId, appToUpdate); } + /** + * Authorize an API resource to the application. + * + * @param applicationId Application ID. + * @param authorizedAPICreationModel API Authorization creation model. + */ + public void addAuthorizedAPI(String applicationId, AuthorizedAPICreationModel authorizedAPICreationModel) { + + try { + String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String authorizedAPIId = authorizedAPICreationModel.getId(); + AuthorizedAPI authorizedAPI = getAuthorizedAPIManagementService().getAuthorizedAPI(applicationId, + authorizedAPIId, tenantDomain); + if (authorizedAPI != null) { + throw handleAuthorizedAPIConflictError(applicationId, authorizedAPIId); + } + + // Validate authorized API creation model. + APIResource apiResource = ApplicationManagementServiceHolder.getApiResourceManager() + .getAPIResourceById(authorizedAPIId, tenantDomain); + if (apiResource == null) { + throw buildClientError(ErrorMessage.API_RESOURCE_NOT_FOUND, authorizedAPIId, tenantDomain); + } + validateAPIResourceScopes(apiResource, authorizedAPICreationModel.getScopes()); + + // Validate policy identifier. + String policyIdentifier = validatePolicy(authorizedAPICreationModel.getPolicyIdentifier()); + + // If API resource has requiresAuthorization set to true, policy identifier should be RBAC. + if (apiResource.isRequiresAuthorization() && + !policyIdentifier.equals(ApplicationManagementConstants.RBAC)) { + throw buildClientError(ErrorMessage.INVALID_POLICY_TYPE_FOR_API_RESOURCE, authorizedAPIId, + policyIdentifier); + } + + getAuthorizedAPIManagementService().addAuthorizedAPI(applicationId, + new AuthorizedAPI.AuthorizedAPIBuilder() + .appId(applicationId) + .apiId(authorizedAPIId) + .policyId(policyIdentifier) + .scopes(authorizedAPICreationModel.getScopes().stream().map( + scope -> new Scope.ScopeBuilder().name(scope).build()).collect(Collectors.toList())) + .build(), tenantDomain); + } catch (IdentityApplicationManagementException e) { + String msg = "Error adding authorized API with id: " + authorizedAPICreationModel.getId() + + " to application with id: " + applicationId; + throw handleIdentityApplicationManagementException(e, msg); + } catch (APIResourceMgtException e) { + String msg = "Error while fetching API resource with id: " + authorizedAPICreationModel.getId(); + throw Utils.buildServerError(msg, e); + } + } + + /** + * Delete an API authorization from the application. + * + * @param applicationId Application ID. + * @param apiId API resource ID. + */ + public void deleteAuthorizedAPI(String applicationId, String apiId) { + + try { + getAuthorizedAPIManagementService().deleteAuthorizedAPI(applicationId, apiId, + CarbonContext.getThreadLocalCarbonContext().getTenantDomain()); + } catch (IdentityApplicationManagementException e) { + String msg = "Error while deleting authorized API with id: " + apiId + " from the application with id: " + + applicationId; + throw handleIdentityApplicationManagementException(e, msg); + } + } + + /** + * Update the API authorization of the application for an API resource. + * + * @param applicationId Application ID. + * @param apiId API resource ID. + * @param authorizedAPIPatchModel API resource patch model. + */ + public void updateAuthorizedAPI(String applicationId, String apiId, + AuthorizedAPIPatchModel authorizedAPIPatchModel) { + + try { + String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + + // Validate added scopes and removed scopes sent in the authorized API patch model. + List addedScopes = authorizedAPIPatchModel.getAddedScopes(); + List removedScopes = authorizedAPIPatchModel.getRemovedScopes(); + addedScopes.removeAll(removedScopes); + + // Validate authorized API patch model. + APIResource apiResource = ApplicationManagementServiceHolder.getApiResourceManager() + .getAPIResourceById(apiId, tenantDomain); + if (apiResource == null) { + throw buildClientError(ErrorMessage.API_RESOURCE_NOT_FOUND, apiId, tenantDomain); + } + validateAPIResourceScopes(apiResource, addedScopes); + + // Remove already authorized scopes from the added scopes list. + AuthorizedAPI currentAuthorizedAPI = getAuthorizedAPIManagementService().getAuthorizedAPI(applicationId, + apiId, tenantDomain); + if (currentAuthorizedAPI == null) { + throw buildClientError(ErrorMessage.AUTHORIZED_API_NOT_FOUND, apiId, applicationId); + } + addedScopes.removeIf(scopeName -> currentAuthorizedAPI.getScopes().stream().anyMatch(scope -> + scope.getName().equals(scopeName))); + + getAuthorizedAPIManagementService().patchAuthorizedAPI(applicationId, apiId, addedScopes, removedScopes, + tenantDomain); + } catch (APIResourceMgtException e) { + String msg = "Error while fetching API resource with id: " + apiId; + throw Utils.buildServerError(msg, e); + } catch (IdentityApplicationManagementException e) { + String msg = "Error while updating authorized API with id: " + apiId + " for the application with id: " + + applicationId; + throw handleIdentityApplicationManagementException(e, msg); + } + } + + /** + * Get Authorized API list. + * + * @param applicationId Application ID. + * @return List of authorized APIs of the application. + */ + public List getAuthorizedAPIs(String applicationId) { + + try { + List authorizedAPIResponses = new ArrayList<>(); + List authorizedAPIs = getAuthorizedAPIManagementService().getAuthorizedAPIs(applicationId, + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()); + if (authorizedAPIs == null) { + return new ArrayList<>(); + } + for (AuthorizedAPI authorizedAPI : authorizedAPIs) { + authorizedAPIResponses.add(new AuthorizedAPIResponse() + .id(authorizedAPI.getAPIId()) + .identifier(authorizedAPI.getAPIIdentifier()) + .displayName(authorizedAPI.getAPIName()) + .policyId(authorizedAPI.getPolicyId()) + .authorizedScopes(createAuthorizedScope(authorizedAPI.getScopes()))); + } + return authorizedAPIResponses; + } catch (IdentityApplicationManagementException e) { + String msg = "Error retrieving authorized APIs of application with id: " + applicationId; + throw handleIdentityApplicationManagementException(e, msg); + } + } + + private String validatePolicy(String policyId) { + + if (StringUtils.isBlank(policyId)) { + // No input provided, use the default policy identifier. + return ApplicationManagementConstants.RBAC; + } + if (StringUtils.equalsIgnoreCase(ApplicationManagementConstants.RBAC, policyId) + || StringUtils.equalsIgnoreCase(ApplicationManagementConstants.NO_POLICY, policyId)) { + return StringUtils.upperCase(policyId); + } else { + throw buildClientError(ErrorMessage.INVALID_POLICY_VALUE); + } + } + + private void validateAPIResourceScopes(APIResource apiResource, List scopes) + throws APIResourceMgtException { + + List apiResourceScopes = apiResource.getScopes(); + if (scopes == null) { + return; + } + for (String scopeName : scopes) { + if (apiResourceScopes.stream().noneMatch(scope -> scope.getName().equals(scopeName))) { + throw buildClientError(ErrorMessage.SCOPES_NOT_FOUND, apiResource.getId(), + CarbonContext.getThreadLocalCarbonContext().getTenantDomain()); + } + } + } + + private List createAuthorizedScope(List scope) { + + return scope.stream().map(s -> new AuthorizedScope() + .name(s.getName()) + .displayName(s.getDisplayName()) + .id(s.getId())) + .collect(Collectors.toList()); + } + private T getInbound(String applicationId, String inboundType, Function getInboundApiModelFunction) { @@ -1526,6 +1722,11 @@ private ApplicationManagementService getApplicationManagementService() { return ApplicationManagementServiceHolder.getApplicationManagementService(); } + private AuthorizedAPIManagementService getAuthorizedAPIManagementService() { + + return ApplicationManagementServiceHolder.getAuthorizedAPIManagementService(); + } + private TemplateManager getTemplateManager() { return ApplicationManagementServiceHolder.getTemplateManager(); @@ -1685,4 +1886,11 @@ private org.wso2.carbon.user.core.common.User getUserFromUserID(String userId) { ErrorMessage.ERROR_RETRIEVING_USERSTORE_MANAGER.getDescription()); } } + + private APIError handleAuthorizedAPIConflictError(String appId, String apiId) { + + return Utils.buildConflictError(ErrorMessage.API_RESOURCE_ALREADY_AUTHORIZED.getCode(), + ErrorMessage.API_RESOURCE_ALREADY_AUTHORIZED.getMessage(), + String.format(ErrorMessage.API_RESOURCE_ALREADY_AUTHORIZED.getDescription(), apiId, appId)); + } } 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/Utils.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/Utils.java index 3fa008b315..aa42e744de 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/Utils.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/Utils.java @@ -206,6 +206,18 @@ public static APIError buildForbiddenError(String errorCode, String message, Str return new APIError(status, errorResponse); } + public static APIError buildConflictError(String errorCode, String message, String description) { + + ErrorResponse errorResponse = new ErrorResponse.Builder() + .withCode(errorCode) + .withMessage(message) + .withDescription(description) + .build(log, description); + + Response.Status status = Response.Status.CONFLICT; + return new APIError(status, errorResponse); + } + private static final Set systemApplications = ApplicationManagementServiceHolder.getApplicationManagementService().getSystemApplications(); 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/impl/ApplicationsApiServiceImpl.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/impl/ApplicationsApiServiceImpl.java index 8c57c012cc..f49e54b6be 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/impl/ApplicationsApiServiceImpl.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/impl/ApplicationsApiServiceImpl.java @@ -28,6 +28,8 @@ import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationPatchModel; import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationTemplateModel; import org.wso2.carbon.identity.api.server.application.management.v1.ApplicationsApiService; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPICreationModel; +import org.wso2.carbon.identity.api.server.application.management.v1.AuthorizedAPIPatchModel; import org.wso2.carbon.identity.api.server.application.management.v1.CustomInboundProtocolConfiguration; import org.wso2.carbon.identity.api.server.application.management.v1.InboundProtocolListItem; import org.wso2.carbon.identity.api.server.application.management.v1.OpenIDConnectConfiguration; @@ -88,6 +90,19 @@ public Response getApplicationTemplate(String templateId) { return Response.ok().entity(applicationManagementService.getApplicationTemplateById(templateId)).build(); } + @Override + public Response getAuthorizedAPIs(String applicationId) { + + return Response.ok().entity(applicationManagementService.getAuthorizedAPIs(applicationId)).build(); + } + + @Override + public Response addAuthorizedAPI(String applicationId, AuthorizedAPICreationModel authorizedAPICreationModel) { + + applicationManagementService.addAuthorizedAPI(applicationId, authorizedAPICreationModel); + return Response.ok().build(); + } + @Override public Response changeApplicationOwner(String applicationId, ApplicationOwner applicationOwner) { @@ -123,6 +138,13 @@ public Response deleteApplicationTemplate(String templateId) { return Response.noContent().build(); } + @Override + public Response deleteAuthorizedAPI(String applicationId, String authorizationId) { + + applicationManagementService.deleteAuthorizedAPI(applicationId, authorizationId); + return Response.noContent().build(); + } + @Override public Response patchApplication(String applicationId, ApplicationPatchModel applicationPatchModel) { @@ -130,6 +152,14 @@ public Response patchApplication(String applicationId, ApplicationPatchModel app return Response.ok().build(); } + @Override + public Response patchAuthorizedAPI(String applicationId, String authorizationId, + AuthorizedAPIPatchModel authorizedAPIPatchModel) { + + applicationManagementService.updateAuthorizedAPI(applicationId, authorizationId, authorizedAPIPatchModel); + return Response.ok().build(); + } + @Override public Response getInboundOAuthConfiguration(String applicationId) { diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/META-INF/cxf/applications-server-v1-cxf.xml b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/META-INF/cxf/applications-server-v1-cxf.xml index 142d89d26c..0fcc456e02 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/META-INF/cxf/applications-server-v1-cxf.xml +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/META-INF/cxf/applications-server-v1-cxf.xml @@ -50,6 +50,14 @@ class="org.wso2.carbon.identity.api.server.application.management.common.ApplicationManagementServiceHolder"> + + + + + + @@ -66,4 +74,8 @@ + + diff --git a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml index a4a43de4ee..49a825b559 100644 --- a/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml +++ b/components/org.wso2.carbon.identity.api.server.application.management/org.wso2.carbon.identity.api.server.application.management.v1/src/main/resources/applications.yaml @@ -611,6 +611,188 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + + /applications/{applicationId}/authorized-apis: + get: + tags: + - Authorized APIs + summary: | + Get authorized APIs of the application. + operationId: getAuthorizedAPIs + description: | + This API provides the capability to retrieve all the authorized APIs of the application.
+ Permission required:
+ * /permission/admin/manage/identity/applicationmgt/view
+ Scope required:
+ * internal_application_mgt_view + parameters: + - name: applicationId + in: path + description: ID of the application. + required: true + schema: + type: string + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AuthorizedAPIResponse' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + tags: + - Authorized APIs + summary: | + Authorized an API to the application + operationId: addAuthorizedAPI + description: | + This API provides the capability to authorized an API to the application.
+ Permission required:
+ * /permission/admin/manage/identity/applicationmgt/create
+ Scope required:
+ * internal_application_mgt_create + parameters: + - name: applicationId + in: path + description: ID of the application. + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizedAPICreationModel' + responses: + '201': + description: Created + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + + /applications/{applicationId}/authorized-apis/{apiId}: + patch: + tags: + - Authorized APIs + summary: | + Update authorized API scopes + operationId: patchAuthorizedAPI + description: | + This API provides the capability to update an authorized API of the application.
+ Permission required:
+ * /permission/admin/manage/identity/applicationmgt/update
+ Scope required:
+ * internal_application_mgt_update + parameters: + - name: applicationId + in: path + description: ID of the application. + required: true + schema: + type: string + - name: apiId + in: path + description: ID of the API resource. + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizedAPIPatchModel' + responses: + '200': + description: OK + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + delete: + tags: + - Authorized APIs + summary: | + Remove API authorization from the application + operationId: deleteAuthorizedAPI + description: | + This API provides the capability to delete an authorized API of the application.
+ Permission required:
+ * /permission/admin/manage/identity/applicationmgt/delete
+ Scope required:
+ * internal_application_mgt_delete + parameters: + - name: applicationId + in: path + description: ID of the application. + required: true + schema: + type: string + - name: apiId + in: path + description: ID of the API resource. + required: true + schema: + type: string + responses: + '204': + description: No Content + '401': + description: Unauthorized + '403': + description: Forbidden + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /applications/resident: get: tags: @@ -3508,6 +3690,68 @@ components: required: - id + AuthorizedAPIResponse: + type: object + properties: + id: + type: string + example: 012df-232gf-545fg-dff23 + identifier: + type: string + example: https://greetings.io/v1/greet + displayName: + type: string + example: Greetings API + policyId: + type: string + example: RBAC + authorizedScopes: + type: array + items: + $ref: '#/components/schemas/AuthorizedScope' + + AuthorizedScope: + type: object + properties: + id: + type: string + example: 012df-232gf-545fg-dff23 + name: + type: string + example: bookings:read + displayName: + type: string + example: Read Bookings + + AuthorizedAPICreationModel: + type: object + properties: + id : + type: string + example: 012df-232gf-545fg-dff23 + policyIdentifier: + type: string + example: RBAC + scopes: + type: array + items: + type: string + example: bookings:read + + AuthorizedAPIPatchModel: + type: object + properties: + addedScopes: + type: array + items: + type: string + example: bookings:edit + removedScopes: + type: array + items: + type: string + example: bookings:view + Error: type: object properties: @@ -3530,4 +3774,4 @@ servers: tenant-domain: default: "carbon.super" server-url: - default: "localhost:9443" + default: "localhost:9443" \ No newline at end of file diff --git a/pom.xml b/pom.xml index b6901e19e2..d8f0f91aa0 100644 --- a/pom.xml +++ b/pom.xml @@ -718,7 +718,7 @@ 1.4 1.2.4 1.8.62 - 5.25.337 + 5.25.350-SNAPSHOT 3.0.5 5.2.0 **/gen/**/*