diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/pom.xml b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/pom.xml index f4f5be051d..0d21ffd532 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/pom.xml +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/pom.xml @@ -52,6 +52,11 @@ spring-web provided + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.common + provided + diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/AuthenticatorsServiceHolder.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/AuthenticatorsServiceHolder.java index 1f53f027f0..990b0fc18c 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/AuthenticatorsServiceHolder.java +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/AuthenticatorsServiceHolder.java @@ -16,6 +16,7 @@ package org.wso2.carbon.identity.api.server.authenticators.common; +import org.wso2.carbon.identity.application.common.ApplicationAuthenticatorService; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.idp.mgt.IdentityProviderManager; @@ -28,6 +29,7 @@ public class AuthenticatorsServiceHolder { private ApplicationManagementService applicationManagementService; private IdentityProviderManager identityProviderManager; + private ApplicationAuthenticatorService applicationAuthenticatorService; private AuthenticatorsServiceHolder() { @@ -77,4 +79,24 @@ public void setIdentityProviderManager(IdentityProviderManager identityProviderM AuthenticatorsServiceHolder.getInstance().identityProviderManager = identityProviderManager; } + + /** + * Get ApplicationAuthenticatorService osgi service. + * + * @return ApplicationAuthenticatorService + */ + public ApplicationAuthenticatorService getApplicationAuthenticatorService() { + + return AuthenticatorsServiceHolder.getInstance().applicationAuthenticatorService; + } + + /** + * Set ApplicationAuthenticatorService osgi service. + * + * @param applicationAuthenticatorService ApplicationAuthenticatorService. + */ + public void setApplicationAuthenticatorService(ApplicationAuthenticatorService applicationAuthenticatorService) { + + AuthenticatorsServiceHolder.getInstance().applicationAuthenticatorService = applicationAuthenticatorService; + } } diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/Constants.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/Constants.java index e021aa890b..a632624d11 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/Constants.java +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/Constants.java @@ -28,6 +28,7 @@ private Constants() { public static final String AUTHENTICATOR_ERROR_PREFIX = "AUT-"; public static final String FEDERATED_AUTHENTICATORS = "federatedAuthenticators"; public static final String AUTHENTICATOR_PATH_COMPONENT = "/authenticators"; + public static final String CONFIGS_AUTHENTICATOR_PATH_COMPONENT = "/configs/authenticators/%s"; public static final String PATH_SEPERATOR = "/"; public static final String PAGE_LINK_REL_NEXT = "next"; public static final String PAGE_LINK_REL_PREVIOUS = "previous"; @@ -70,6 +71,11 @@ public enum ErrorMessage { "Filter needs to be in the format ++. Eg: tag+eq+2FA"), ERROR_CODE_UNSUPPORTED_FILTER_ATTRIBUTE("60002", "Unsupported filter attribute.", "The filter attribute '%s' is not supported."), + ERROR_CODE_INVALID_ENDPOINT_CONFIG("60003", "Invalid endpoint configuration provided.", + "Invalid endpoint configuration is provided for the authenticator %s."), + ERROR_CODE_ERROR_AUTHENTICATOR_NOT_FOUND("60004", "Authenticator not found.", + "Authenticator not found by the given name: %s."), + ERROR_CODE_ERROR_LISTING_AUTHENTICATORS("65001", "Unable to list the existing authenticators.", "Server encountered an error while listing the authenticators."), ERROR_CODE_ERROR_LISTING_IDPS("65002", "Unable to list the existing identity providers.", diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/factory/ApplicationAuthenticatorOSGIServiceFactory.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/factory/ApplicationAuthenticatorOSGIServiceFactory.java new file mode 100644 index 0000000000..e8c4dcd764 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.common/src/main/java/org/wso2/carbon/identity/api/server/authenticators/common/factory/ApplicationAuthenticatorOSGIServiceFactory.java @@ -0,0 +1,54 @@ +/* + * 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.authenticators.common.factory; + +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.application.common.ApplicationAuthenticatorService; + +/** + * Factory Beans serves as a factory for creating other beans within the IOC container. This factory bean is used to + * instantiate the ApplicationAuthenticatorService type of object inside the container. + */ +public class ApplicationAuthenticatorOSGIServiceFactory extends AbstractFactoryBean { + + private ApplicationAuthenticatorService applicationAuthenticatorService; + + @Override + public Class getObjectType() { + + return Object.class; + } + + @Override + protected ApplicationAuthenticatorService createInstance() throws Exception { + + if (this.applicationAuthenticatorService == null) { + ApplicationAuthenticatorService taskOperationService = (ApplicationAuthenticatorService) + PrivilegedCarbonContext.getThreadLocalCarbonContext().getOSGiService( + ApplicationAuthenticatorService.class, null); + if (taskOperationService != null) { + this.applicationAuthenticatorService = taskOperationService; + } else { + throw new Exception("Unable to retrieve ApplicationAuthenticatorService service."); + } + } + return this.applicationAuthenticatorService; + } +} diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApi.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApi.java index 1d7fd0142f..e13b242706 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApi.java +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApi.java @@ -25,6 +25,8 @@ import org.wso2.carbon.identity.api.server.authenticators.v1.model.Authenticator; import org.wso2.carbon.identity.api.server.authenticators.v1.model.ConnectedApps; import org.wso2.carbon.identity.api.server.authenticators.v1.model.Error; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorCreation; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorUpdate; import org.wso2.carbon.identity.api.server.authenticators.v1.AuthenticatorsApiService; import javax.validation.Valid; @@ -42,6 +44,29 @@ public class AuthenticatorsApi { @Autowired private AuthenticatorsApiService delegate; + @Valid + @POST + @Path("/custom") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Create a new user defined local authenticator. ", notes = "This API provides the capability to create a new user defined local authenticator.
Permission required:
* /permission/admin/manage/custom_authenticator/create
Scope required:
* internal_custom_authenticator_create
", response = Authenticator.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "User defined local authenticators", }) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Successful response", response = Authenticator.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 = 500, message = "Server Error", response = Error.class) + }) + public Response addUserDefinedLocalAuthenticator(@ApiParam(value = "This represents the user defined local authenticator to be created." ,required=true) @Valid UserDefinedLocalAuthenticatorCreation userDefinedLocalAuthenticatorCreation) { + + return delegate.addUserDefinedLocalAuthenticator(userDefinedLocalAuthenticatorCreation ); + } + @Valid @GET @@ -91,6 +116,29 @@ public Response authenticatorsMetaTagsGet() { return delegate.authenticatorsMetaTagsGet(); } + @Valid + @DELETE + @Path("/custom/{authenticator-id}") + + @Produces({ "application/json" }) + @ApiOperation(value = "Delete a user defined local authenticator. ", notes = "This API provides the capability to delete a user defined local authenticators.
Permission required:
* /permission/admin/manage/custom_authenticator/delete
Scope required:
* internal_custom_authenticator_delete
", response = Void.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "User defined local authenticators", }) + @ApiResponses(value = { + @ApiResponse(code = 204, message = "Successful response", 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 = 500, message = "Server Error", response = Error.class) + }) + public Response deleteUserDefinedLocalAuthenticator(@ApiParam(value = "ID of an authenticator",required=true) @PathParam("authenticator-id") String authenticatorId) { + + return delegate.deleteUserDefinedLocalAuthenticator(authenticatorId ); + } + @Valid @GET @Path("/{authenticator-id}/connected-apps") @@ -101,7 +149,7 @@ public Response authenticatorsMetaTagsGet() { @Authorization(value = "OAuth2", scopes = { }) - }, tags={ "Connected apps of local authenticators" }) + }, tags={ "Connected apps of local authenticators", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "Successful Response", response = ConnectedApps.class), @ApiResponse(code = 400, message = "Bad Request", response = Error.class), @@ -115,4 +163,27 @@ public Response getConnectedAppsOfLocalAuthenticator(@ApiParam(value = "ID of an return delegate.getConnectedAppsOfLocalAuthenticator(authenticatorId, limit, offset ); } + @Valid + @PUT + @Path("/custom/{authenticator-id}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Update a user defined local authenticator. ", notes = "This API provides the capability to update a user defined local authenticator configurations.
Permission required:
* /permission/admin/manage/custom_authenticator/update
Scope required:
* internal_custom_authenticator_update
", response = Authenticator.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "User defined local authenticators" }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successful response", response = Authenticator.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 = 500, message = "Server Error", response = Error.class) + }) + public Response updateUserDefinedLocalAuthenticator(@ApiParam(value = "ID of an authenticator",required=true) @PathParam("authenticator-id") String authenticatorId, @ApiParam(value = "This represents the user defined local authenticator to be created." ,required=true) @Valid UserDefinedLocalAuthenticatorUpdate userDefinedLocalAuthenticatorUpdate) { + + return delegate.updateUserDefinedLocalAuthenticator(authenticatorId, userDefinedLocalAuthenticatorUpdate ); + } + } diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApiService.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApiService.java index 9eba016ca1..145b8b45c0 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApiService.java +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/AuthenticatorsApiService.java @@ -25,14 +25,22 @@ import org.wso2.carbon.identity.api.server.authenticators.v1.model.Authenticator; import org.wso2.carbon.identity.api.server.authenticators.v1.model.ConnectedApps; import org.wso2.carbon.identity.api.server.authenticators.v1.model.Error; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorCreation; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorUpdate; import javax.ws.rs.core.Response; public interface AuthenticatorsApiService { + public Response addUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorCreation userDefinedLocalAuthenticatorCreation); + public Response authenticatorsGet(String filter, Integer limit, Integer offset); public Response authenticatorsMetaTagsGet(); + public Response deleteUserDefinedLocalAuthenticator(String authenticatorId); + public Response getConnectedAppsOfLocalAuthenticator(String authenticatorId, Integer limit, Integer offset); + + public Response updateUserDefinedLocalAuthenticator(String authenticatorId, UserDefinedLocalAuthenticatorUpdate userDefinedLocalAuthenticatorUpdate); } diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/AuthenticationType.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/AuthenticationType.java new file mode 100644 index 0000000000..b3df1de0ed --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/AuthenticationType.java @@ -0,0 +1,166 @@ +/* + * 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.authenticators.v1.model; + +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.HashMap; +import java.util.List; +import java.util.Map; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class AuthenticationType { + + +@XmlType(name="TypeEnum") +@XmlEnum(String.class) +public enum TypeEnum { + + @XmlEnumValue("NONE") NONE(String.valueOf("NONE")), @XmlEnumValue("BEARER") BEARER(String.valueOf("BEARER")), @XmlEnumValue("API_KEY") API_KEY(String.valueOf("API_KEY")), @XmlEnumValue("BASIC") BASIC(String.valueOf("BASIC")); + + + private String value; + + TypeEnum(String v) { + value = v; + } + + public String value() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + public static TypeEnum fromValue(String value) { + for (TypeEnum b : TypeEnum.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } +} + + private TypeEnum type; + private Map properties = new HashMap<>(); + + + /** + **/ + public AuthenticationType type(TypeEnum type) { + + this.type = type; + return this; + } + + @ApiModelProperty(example = "BASIC", required = true, value = "") + @JsonProperty("type") + @Valid + @NotNull(message = "Property type cannot be null.") + + public TypeEnum getType() { + return type; + } + public void setType(TypeEnum type) { + this.type = type; + } + + /** + **/ + public AuthenticationType properties(Map properties) { + + this.properties = properties; + return this; + } + + @ApiModelProperty(example = "{\"username\":\"auth_username\",\"password\":\"auth_password\"}", required = true, value = "") + @JsonProperty("properties") + @Valid + @NotNull(message = "Property properties cannot be null.") + + public Map getProperties() { + return properties; + } + public void setProperties(Map properties) { + this.properties = properties; + } + + + public AuthenticationType putPropertiesItem(String key, Object propertiesItem) { + this.properties.put(key, propertiesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuthenticationType authenticationType = (AuthenticationType) o; + return Objects.equals(this.type, authenticationType.type) && + Objects.equals(this.properties, authenticationType.properties); + } + + @Override + public int hashCode() { + return Objects.hash(type, properties); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AuthenticationType {\n"); + + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" properties: ").append(toIndentedString(properties)).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.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/Endpoint.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/Endpoint.java new file mode 100644 index 0000000000..fbf614fe71 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/Endpoint.java @@ -0,0 +1,120 @@ +/* + * 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.authenticators.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.AuthenticationType; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class Endpoint { + + private String uri; + private AuthenticationType authentication; + + /** + **/ + public Endpoint uri(String uri) { + + this.uri = uri; + return this; + } + + @ApiModelProperty(example = "https://abc.com/token", value = "") + @JsonProperty("uri") + @Valid @Pattern(regexp="^https?://.+") + public String getUri() { + return uri; + } + public void setUri(String uri) { + this.uri = uri; + } + + /** + **/ + public Endpoint authentication(AuthenticationType authentication) { + + this.authentication = authentication; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("authentication") + @Valid + public AuthenticationType getAuthentication() { + return authentication; + } + public void setAuthentication(AuthenticationType authentication) { + this.authentication = authentication; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Endpoint endpoint = (Endpoint) o; + return Objects.equals(this.uri, endpoint.uri) && + Objects.equals(this.authentication, endpoint.authentication); + } + + @Override + public int hashCode() { + return Objects.hash(uri, authentication); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class Endpoint {\n"); + + sb.append(" uri: ").append(toIndentedString(uri)).append("\n"); + sb.append(" authentication: ").append(toIndentedString(authentication)).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.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/UserDefinedLocalAuthenticatorCreation.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/UserDefinedLocalAuthenticatorCreation.java new file mode 100644 index 0000000000..5f41aecca3 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/UserDefinedLocalAuthenticatorCreation.java @@ -0,0 +1,290 @@ +/* + * 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.authenticators.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.Endpoint; +import javax.validation.constraints.*; + +/** + * This represents the configuration for creating the user defined local authenticator. + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "This represents the configuration for creating the user defined local authenticator.") +public class UserDefinedLocalAuthenticatorCreation { + + private String name; + private String id; + private String displayName; + private Boolean isEnabled; + +@XmlType(name="AuthenticationTypeEnum") +@XmlEnum(String.class) +public enum AuthenticationTypeEnum { + + @XmlEnumValue("IDENTIFICATION") IDENTIFICATION(String.valueOf("IDENTIFICATION")), @XmlEnumValue("VERIFICATION") VERIFICATION(String.valueOf("VERIFICATION")); + + + private String value; + + AuthenticationTypeEnum(String v) { + value = v; + } + + public String value() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + public static AuthenticationTypeEnum fromValue(String value) { + for (AuthenticationTypeEnum b : AuthenticationTypeEnum.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } +} + + private AuthenticationTypeEnum authenticationType; + private String image; + private String description; + private Endpoint endpoint; + + /** + **/ + public UserDefinedLocalAuthenticatorCreation name(String name) { + + this.name = name; + return this; + } + + @ApiModelProperty(example = "CustomAuthenticator", required = true, value = "") + @JsonProperty("name") + @Valid + @NotNull(message = "Property name cannot be null.") + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + /** + **/ + public UserDefinedLocalAuthenticatorCreation id(String id) { + + this.id = id; + return this; + } + + @ApiModelProperty(example = "Q3VzdG9tQXV0aGVudGljYXRvcg==", value = "") + @JsonProperty("id") + @Valid + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + /** + **/ + public UserDefinedLocalAuthenticatorCreation displayName(String displayName) { + + this.displayName = displayName; + return this; + } + + @ApiModelProperty(example = "Custom auth", required = true, value = "") + @JsonProperty("displayName") + @Valid + @NotNull(message = "Property displayName cannot be null.") + + public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + **/ + public UserDefinedLocalAuthenticatorCreation isEnabled(Boolean isEnabled) { + + this.isEnabled = isEnabled; + return this; + } + + @ApiModelProperty(example = "true", required = true, value = "") + @JsonProperty("isEnabled") + @Valid + @NotNull(message = "Property isEnabled cannot be null.") + + public Boolean getIsEnabled() { + return isEnabled; + } + public void setIsEnabled(Boolean isEnabled) { + this.isEnabled = isEnabled; + } + + /** + **/ + public UserDefinedLocalAuthenticatorCreation authenticationType(AuthenticationTypeEnum authenticationType) { + + this.authenticationType = authenticationType; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("authenticationType") + @Valid + public AuthenticationTypeEnum getAuthenticationType() { + return authenticationType; + } + public void setAuthenticationType(AuthenticationTypeEnum authenticationType) { + this.authenticationType = authenticationType; + } + + /** + **/ + public UserDefinedLocalAuthenticatorCreation image(String image) { + + this.image = image; + return this; + } + + @ApiModelProperty(example = "https://custom-authenticator-logo-url", value = "") + @JsonProperty("image") + @Valid + public String getImage() { + return image; + } + public void setImage(String image) { + this.image = image; + } + + /** + **/ + public UserDefinedLocalAuthenticatorCreation description(String description) { + + this.description = description; + return this; + } + + @ApiModelProperty(example = "The user defined custom local authenticator.", value = "") + @JsonProperty("description") + @Valid + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + /** + **/ + public UserDefinedLocalAuthenticatorCreation endpoint(Endpoint endpoint) { + + this.endpoint = endpoint; + return this; + } + + @ApiModelProperty(required = true, value = "") + @JsonProperty("endpoint") + @Valid + @NotNull(message = "Property endpoint cannot be null.") + + public Endpoint getEndpoint() { + return endpoint; + } + public void setEndpoint(Endpoint endpoint) { + this.endpoint = endpoint; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UserDefinedLocalAuthenticatorCreation userDefinedLocalAuthenticatorCreation = (UserDefinedLocalAuthenticatorCreation) o; + return Objects.equals(this.name, userDefinedLocalAuthenticatorCreation.name) && + Objects.equals(this.id, userDefinedLocalAuthenticatorCreation.id) && + Objects.equals(this.displayName, userDefinedLocalAuthenticatorCreation.displayName) && + Objects.equals(this.isEnabled, userDefinedLocalAuthenticatorCreation.isEnabled) && + Objects.equals(this.authenticationType, userDefinedLocalAuthenticatorCreation.authenticationType) && + Objects.equals(this.image, userDefinedLocalAuthenticatorCreation.image) && + Objects.equals(this.description, userDefinedLocalAuthenticatorCreation.description) && + Objects.equals(this.endpoint, userDefinedLocalAuthenticatorCreation.endpoint); + } + + @Override + public int hashCode() { + return Objects.hash(name, id, displayName, isEnabled, authenticationType, image, description, endpoint); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class UserDefinedLocalAuthenticatorCreation {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" displayName: ").append(toIndentedString(displayName)).append("\n"); + sb.append(" isEnabled: ").append(toIndentedString(isEnabled)).append("\n"); + sb.append(" authenticationType: ").append(toIndentedString(authenticationType)).append("\n"); + sb.append(" image: ").append(toIndentedString(image)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" endpoint: ").append(toIndentedString(endpoint)).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.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/UserDefinedLocalAuthenticatorUpdate.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/UserDefinedLocalAuthenticatorUpdate.java new file mode 100644 index 0000000000..d31ff73267 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/gen/java/org/wso2/carbon/identity/api/server/authenticators/v1/model/UserDefinedLocalAuthenticatorUpdate.java @@ -0,0 +1,192 @@ +/* + * 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.authenticators.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.Endpoint; +import javax.validation.constraints.*; + +/** + * TThis represents the configuration for updating user defined local authenticator. + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "TThis represents the configuration for updating user defined local authenticator.") +public class UserDefinedLocalAuthenticatorUpdate { + + private String displayName; + private Boolean isEnabled; + private String image; + private String description; + private Endpoint endpoint; + + /** + **/ + public UserDefinedLocalAuthenticatorUpdate displayName(String displayName) { + + this.displayName = displayName; + return this; + } + + @ApiModelProperty(example = "Custom auth", required = true, value = "") + @JsonProperty("displayName") + @Valid + @NotNull(message = "Property displayName cannot be null.") + + public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + **/ + public UserDefinedLocalAuthenticatorUpdate isEnabled(Boolean isEnabled) { + + this.isEnabled = isEnabled; + return this; + } + + @ApiModelProperty(example = "true", required = true, value = "") + @JsonProperty("isEnabled") + @Valid + @NotNull(message = "Property isEnabled cannot be null.") + + public Boolean getIsEnabled() { + return isEnabled; + } + public void setIsEnabled(Boolean isEnabled) { + this.isEnabled = isEnabled; + } + + /** + **/ + public UserDefinedLocalAuthenticatorUpdate image(String image) { + + this.image = image; + return this; + } + + @ApiModelProperty(example = "https://custom-authenticator-logo-url", value = "") + @JsonProperty("image") + @Valid + public String getImage() { + return image; + } + public void setImage(String image) { + this.image = image; + } + + /** + **/ + public UserDefinedLocalAuthenticatorUpdate description(String description) { + + this.description = description; + return this; + } + + @ApiModelProperty(example = "The user defined custom local authenticator.", value = "") + @JsonProperty("description") + @Valid + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + /** + **/ + public UserDefinedLocalAuthenticatorUpdate endpoint(Endpoint endpoint) { + + this.endpoint = endpoint; + return this; + } + + @ApiModelProperty(required = true, value = "") + @JsonProperty("endpoint") + @Valid + @NotNull(message = "Property endpoint cannot be null.") + + public Endpoint getEndpoint() { + return endpoint; + } + public void setEndpoint(Endpoint endpoint) { + this.endpoint = endpoint; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UserDefinedLocalAuthenticatorUpdate userDefinedLocalAuthenticatorUpdate = (UserDefinedLocalAuthenticatorUpdate) o; + return Objects.equals(this.displayName, userDefinedLocalAuthenticatorUpdate.displayName) && + Objects.equals(this.isEnabled, userDefinedLocalAuthenticatorUpdate.isEnabled) && + Objects.equals(this.image, userDefinedLocalAuthenticatorUpdate.image) && + Objects.equals(this.description, userDefinedLocalAuthenticatorUpdate.description) && + Objects.equals(this.endpoint, userDefinedLocalAuthenticatorUpdate.endpoint); + } + + @Override + public int hashCode() { + return Objects.hash(displayName, isEnabled, image, description, endpoint); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class UserDefinedLocalAuthenticatorUpdate {\n"); + + sb.append(" displayName: ").append(toIndentedString(displayName)).append("\n"); + sb.append(" isEnabled: ").append(toIndentedString(isEnabled)).append("\n"); + sb.append(" image: ").append(toIndentedString(image)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" endpoint: ").append(toIndentedString(endpoint)).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.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/core/ServerAuthenticatorManagementService.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/core/ServerAuthenticatorManagementService.java index c888cfafdc..03ada6e804 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/core/ServerAuthenticatorManagementService.java +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/core/ServerAuthenticatorManagementService.java @@ -23,13 +23,17 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.identity.api.server.authenticators.common.AuthenticatorsServiceHolder; import org.wso2.carbon.identity.api.server.authenticators.common.Constants; +import org.wso2.carbon.identity.api.server.authenticators.v1.impl.LocalAuthenticatorConfigBuilderFactory; import org.wso2.carbon.identity.api.server.authenticators.v1.model.Authenticator; import org.wso2.carbon.identity.api.server.authenticators.v1.model.ConnectedApp; import org.wso2.carbon.identity.api.server.authenticators.v1.model.ConnectedApps; import org.wso2.carbon.identity.api.server.authenticators.v1.model.Link; import org.wso2.carbon.identity.api.server.authenticators.v1.model.NameFilter; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorCreation; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorUpdate; import org.wso2.carbon.identity.api.server.common.ContextLoader; import org.wso2.carbon.identity.api.server.common.error.APIError; import org.wso2.carbon.identity.api.server.common.error.ErrorResponse; @@ -37,10 +41,14 @@ import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementServerException; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtClientException; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtServerException; 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.LocalAuthenticatorConfig; import org.wso2.carbon.identity.application.common.model.RequestPathAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.core.model.ExpressionNode; @@ -66,6 +74,7 @@ import static org.wso2.carbon.identity.api.server.authenticators.common.Constants.AUTHENTICATOR_PATH_COMPONENT; import static org.wso2.carbon.identity.api.server.common.Constants.V1_API_PATH_COMPONENT; +import static org.wso2.carbon.identity.api.server.common.Util.base64URLDecode; import static org.wso2.carbon.identity.api.server.common.Util.base64URLEncode; /** @@ -107,7 +116,12 @@ public List getAuthenticators(String filter, Integer limit, Integ LocalAuthenticatorConfig[] localAuthenticatorConfigs = AuthenticatorsServiceHolder.getInstance() .getApplicationManagementService().getAllLocalAuthenticators(ContextLoader .getTenantDomainFromContext()); - + List userDefinedLocalAuthConfigs = getApplicationAuthenticatorService() + .getAllUserDefinedLocalAuthenticators(ContextLoader.getTenantDomainFromContext()); + if (CollectionUtils.isNotEmpty(userDefinedLocalAuthConfigs)) { + localAuthenticatorConfigs = (LocalAuthenticatorConfig[]) ArrayUtils.addAll(localAuthenticatorConfigs, + userDefinedLocalAuthConfigs.toArray(new LocalAuthenticatorConfig[0])); + } int localAuthenticatorsCount = localAuthenticatorConfigs.length; RequestPathAuthenticatorConfig[] requestPathAuthenticatorConfigs = new RequestPathAuthenticatorConfig[0]; @@ -147,6 +161,8 @@ public List getAuthenticators(String filter, Integer limit, Integ null); } catch (IdentityProviderManagementException e) { throw handleIdPException(e, Constants.ErrorMessage.ERROR_CODE_ERROR_LISTING_IDPS, null); + } catch (AuthenticatorMgtException e) { + throw handleAuthenticatorException(e); } } @@ -193,6 +209,69 @@ public ConnectedApps getConnectedAppsOfLocalAuthenticator(String authenticatorId } } + /** + * Add the user defined local authenticator. + * + * @param config The user defined local authenticator update request. + * @return The created authenticator. + */ + public Authenticator addUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorCreation config) { + + try { + UserDefinedLocalAuthenticatorConfig createdConfig = getApplicationAuthenticatorService() + .addUserDefinedLocalAuthenticator( + LocalAuthenticatorConfigBuilderFactory.build(config), + CarbonContext.getThreadLocalCarbonContext().getTenantDomain()); + return LocalAuthenticatorConfigBuilderFactory.build(createdConfig); + } catch (AuthenticatorMgtException e) { + throw handleAuthenticatorException(e); + } + } + + /** + * Deletes the user defined local authenticator. + * + * @param authenticatorId The authenticator ID. + */ + public void deleteUserDefinedLocalAuthenticator(String authenticatorId) { + + try { + getApplicationAuthenticatorService().deleteUserDefinedLocalAuthenticator(base64URLDecode(authenticatorId), + CarbonContext.getThreadLocalCarbonContext().getTenantDomain()); + } catch (AuthenticatorMgtException e) { + throw handleAuthenticatorException(e); + } + } + + /** + * Updates the user defined local authenticator. + * + * @param authenticatorId The authenticator ID. + * @param config The user defined local authenticator update request. + * @return The updated authenticator. + */ + public Authenticator updateUserDefinedLocalAuthenticator( + String authenticatorId, UserDefinedLocalAuthenticatorUpdate config) { + + try { + String authenticatorName = base64URLDecode(authenticatorId); + String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + LocalAuthenticatorConfig existingAuthenticator = getApplicationAuthenticatorService() + .getLocalAuthenticatorByName(authenticatorName, tenantDomain); + if (existingAuthenticator == null) { + throw handleException(Response.Status.NOT_FOUND, + Constants.ErrorMessage.ERROR_CODE_ERROR_AUTHENTICATOR_NOT_FOUND, authenticatorName); + } + UserDefinedLocalAuthenticatorConfig updatedConfig = getApplicationAuthenticatorService() + .updateUserDefinedLocalAuthenticator( + LocalAuthenticatorConfigBuilderFactory.build(config, existingAuthenticator), + tenantDomain); + return LocalAuthenticatorConfigBuilderFactory.build(updatedConfig); + } catch (AuthenticatorMgtException e) { + throw handleAuthenticatorException(e); + } + } + private ConnectedApps createConnectedAppsResponse(String resourceId, ConnectedAppsResult connectedAppsResult) { ConnectedApps connectedAppsResponse = new ConnectedApps(); @@ -383,9 +462,8 @@ private List getDistinctTags(IdentityProvider identityProvider) { if (fedAuthConfigs != null) { for (FederatedAuthenticatorConfig config : fedAuthConfigs) { if (config.isEnabled()) { - FederatedAuthenticatorConfig federatedAuthenticatorConfig = - ApplicationAuthenticatorService.getInstance() - .getFederatedAuthenticatorByName(config.getName()); + FederatedAuthenticatorConfig federatedAuthenticatorConfig = getApplicationAuthenticatorService() + .getFederatedAuthenticatorByName(config.getName()); if (federatedAuthenticatorConfig != null) { String[] tags = federatedAuthenticatorConfig.getTags(); if (ArrayUtils.isNotEmpty(tags)) { @@ -908,6 +986,47 @@ private APIError handleIdPException(IdentityProviderManagementException e, return new APIError(status, errorResponse); } + /** + * Handle IdentityProviderManagementException, extract error code, error description and status code to be sent + * in the response. + * + * @param e IdentityProviderManagementException. + * @return APIError. + */ + private APIError handleAuthenticatorException(AuthenticatorMgtException e) { + + ErrorResponse errorResponse = new ErrorResponse.Builder() + .withCode(e.getErrorCode()) + .withMessage(e.getMessage()) + .withDescription(e.getDescription()).build(); + Response.Status status; + + if (e instanceof AuthenticatorMgtClientException) { + if (e.getErrorCode() != null) { + String errorCode = e.getErrorCode(); + errorCode = + errorCode.contains(org.wso2.carbon.identity.api.server.common.Constants.ERROR_CODE_DELIMITER) ? + errorCode : Constants.AUTHENTICATOR_ERROR_PREFIX + errorCode; + errorResponse.setCode(errorCode); + } + errorResponse.setDescription(e.getDescription()); + status = Response.Status.BAD_REQUEST; + } else if (e instanceof AuthenticatorMgtServerException) { + if (e.getErrorCode() != null) { + String errorCode = e.getErrorCode(); + errorCode = + errorCode.contains(org.wso2.carbon.identity.api.server.common.Constants.ERROR_CODE_DELIMITER) ? + errorCode : Constants.AUTHENTICATOR_ERROR_PREFIX + errorCode; + errorResponse.setCode(errorCode); + } + errorResponse.setDescription(e.getDescription()); + status = Response.Status.INTERNAL_SERVER_ERROR; + } else { + status = Response.Status.INTERNAL_SERVER_ERROR; + } + return new APIError(status, errorResponse); + } + /** * Handle exceptions generated in the API. * @@ -986,4 +1105,9 @@ private void handleNotImplementedCapabilities(Integer limit, Integer offset) { throw new APIError(status, errorResponse); } } + + private ApplicationAuthenticatorService getApplicationAuthenticatorService() { + + return AuthenticatorsServiceHolder.getInstance().getApplicationAuthenticatorService(); + } } diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/impl/AuthenticatorsApiServiceImpl.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/impl/AuthenticatorsApiServiceImpl.java index 1a1b6f6dd4..f3dd6eb6f9 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/impl/AuthenticatorsApiServiceImpl.java +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/impl/AuthenticatorsApiServiceImpl.java @@ -19,9 +19,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.wso2.carbon.identity.api.server.authenticators.v1.AuthenticatorsApiService; import org.wso2.carbon.identity.api.server.authenticators.v1.core.ServerAuthenticatorManagementService; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.Authenticator; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorCreation; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorUpdate; +import org.wso2.carbon.identity.api.server.common.ContextLoader; +import java.net.URI; import javax.ws.rs.core.Response; +import static org.wso2.carbon.identity.api.server.common.Constants.V1_API_PATH_COMPONENT; + /** * Implementation of the Server Authenticators Rest API. */ @@ -42,10 +49,36 @@ public Response authenticatorsMetaTagsGet() { return Response.ok().entity(authenticatorManagementService.getTags()).build(); } + @Override + public Response addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorCreation userDefinedLocalAuthenticatorCreation) { + + Authenticator response = authenticatorManagementService + .addUserDefinedLocalAuthenticator(userDefinedLocalAuthenticatorCreation); + URI location = ContextLoader.buildURIForHeader(V1_API_PATH_COMPONENT + + "/authenticator/custom/" + response.getId()); + return Response.created(location).entity(response).build(); + } + + @Override + public Response deleteUserDefinedLocalAuthenticator(String authenticatorId) { + + authenticatorManagementService.deleteUserDefinedLocalAuthenticator(authenticatorId); + return Response.noContent().build(); + } + @Override public Response getConnectedAppsOfLocalAuthenticator(String authenticatorId, Integer limit, Integer offset) { return Response.ok().entity(authenticatorManagementService .getConnectedAppsOfLocalAuthenticator(authenticatorId, limit, offset)).build(); } + + @Override + public Response updateUserDefinedLocalAuthenticator( + String authenticatorId, UserDefinedLocalAuthenticatorUpdate userDefinedLocalAuthenticatorUpdate) { + + return Response.ok().entity(authenticatorManagementService + .updateUserDefinedLocalAuthenticator(authenticatorId, userDefinedLocalAuthenticatorUpdate)).build(); + } } diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/impl/LocalAuthenticatorConfigBuilderFactory.java b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/impl/LocalAuthenticatorConfigBuilderFactory.java new file mode 100644 index 0000000000..0e36abed91 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/java/org/wso2/carbon/identity/api/server/authenticators/v1/impl/LocalAuthenticatorConfigBuilderFactory.java @@ -0,0 +1,145 @@ +/* + * 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.authenticators.v1.impl; + +import org.wso2.carbon.identity.api.server.authenticators.common.Constants; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.Authenticator; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.Endpoint; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorCreation; +import org.wso2.carbon.identity.api.server.authenticators.v1.model.UserDefinedLocalAuthenticatorUpdate; +import org.wso2.carbon.identity.api.server.common.ContextLoader; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtClientException; +import org.wso2.carbon.identity.application.common.model.LocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.UserDefinedAuthenticatorEndpointConfig; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants; + +import java.util.Arrays; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; + +import static org.wso2.carbon.identity.api.server.authenticators.common.Constants.CONFIGS_AUTHENTICATOR_PATH_COMPONENT; +import static org.wso2.carbon.identity.api.server.authenticators.common.Constants.ErrorMessage.ERROR_CODE_INVALID_ENDPOINT_CONFIG; +import static org.wso2.carbon.identity.api.server.common.Constants.V1_API_PATH_COMPONENT; +import static org.wso2.carbon.identity.api.server.common.Util.base64URLEncode; + +/** + * The factory class for building user defined local authenticator configuration related models. + */ +public class LocalAuthenticatorConfigBuilderFactory { + + private static final String TAG_2FA = "2FA"; + + /** + * Builds the authenticator model from the UserDefinedLocalAuthenticatorConfig. + * + * @param config The user defined local authenticator configuration. + * @return The authenticator model. + */ + public static Authenticator build(UserDefinedLocalAuthenticatorConfig config) { + + Authenticator authenticator = new Authenticator(); + String authenticatorId = base64URLEncode(config.getName()); + authenticator.setName(config.getName()); + authenticator.setId(authenticatorId); + authenticator.setDisplayName(config.getDisplayName()); + authenticator.setIsEnabled(config.isEnabled()); + authenticator.setDefinedBy(Authenticator.DefinedByEnum.USER); + authenticator.setType(Authenticator.TypeEnum.LOCAL); + authenticator.setTags(Arrays.asList(config.getTags())); + authenticator.setSelf(ContextLoader.buildURIForBody(String.format(V1_API_PATH_COMPONENT + + CONFIGS_AUTHENTICATOR_PATH_COMPONENT, authenticatorId)).toString()); + + return authenticator; + } + + /** + * Builds the UserDefinedLocalAuthenticatorConfig from the user defined local authenticator creation request. + * + * @param config The user defined local authenticator creation request. + * @return The user defined local authenticator configuration. + * @throws AuthenticatorMgtClientException If an error occurs while building the configuration. + */ + public static UserDefinedLocalAuthenticatorConfig build(UserDefinedLocalAuthenticatorCreation config) + throws AuthenticatorMgtClientException { + + String authenticationType = AuthenticatorPropertyConstants.AuthenticationType.IDENTIFICATION.toString(); + if (config.getAuthenticationType() != null) { + authenticationType = config.getAuthenticationType().toString(); + } + UserDefinedLocalAuthenticatorConfig authConfig = new UserDefinedLocalAuthenticatorConfig( + AuthenticatorPropertyConstants.AuthenticationType.valueOf(authenticationType)); + authConfig.setName(config.getName()); + authConfig.setDisplayName(config.getDisplayName()); + authConfig.setEnabled(config.getIsEnabled()); + authConfig.setEndpointConfig(buildEndpointConfig(config.getEndpoint())); + + return authConfig; + } + + /** + * Builds the UserDefinedLocalAuthenticatorConfig from the user defined local authenticator update request. + * + * @param config The user defined local authenticator update request. + * @param existingConfig The existing user defined local authenticator configuration. + * @return The user defined local authenticator configuration. + * @throws AuthenticatorMgtClientException If an error occurs while building the configuration. + */ + public static UserDefinedLocalAuthenticatorConfig build(UserDefinedLocalAuthenticatorUpdate config, + LocalAuthenticatorConfig existingConfig) throws AuthenticatorMgtClientException { + + UserDefinedLocalAuthenticatorConfig authConfig = new UserDefinedLocalAuthenticatorConfig( + resolveAuthenticationType(existingConfig)); + authConfig.setName(existingConfig.getName()); + authConfig.setDisplayName(config.getDisplayName()); + authConfig.setEnabled(config.getIsEnabled()); + authConfig.setEndpointConfig(buildEndpointConfig(config.getEndpoint())); + + return authConfig; + } + + private static UserDefinedAuthenticatorEndpointConfig buildEndpointConfig(Endpoint endpointConfig) + throws AuthenticatorMgtClientException { + + try { + UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder endpointConfigBuilder = + new UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder(); + endpointConfigBuilder.uri(endpointConfig.getUri()); + endpointConfigBuilder.authenticationType(endpointConfig.getAuthentication().getType().toString()); + endpointConfigBuilder.authenticationProperties(endpointConfig.getAuthentication().getProperties() + .entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, entry -> entry.getValue().toString()))); + return endpointConfigBuilder.build(); + } catch (NoSuchElementException | IllegalArgumentException e) { + Constants.ErrorMessage error = ERROR_CODE_INVALID_ENDPOINT_CONFIG; + throw new AuthenticatorMgtClientException(error.getCode(), error.getMessage(), e.getMessage()); + } + } + + private static AuthenticatorPropertyConstants.AuthenticationType resolveAuthenticationType( + LocalAuthenticatorConfig config) { + + if (Arrays.asList(config.getTags()).contains(TAG_2FA)) { + return AuthenticatorPropertyConstants.AuthenticationType.VERIFICATION; + } else { + return AuthenticatorPropertyConstants.AuthenticationType.IDENTIFICATION; + } + } +} diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/META-INF/cxf/authenticators-server-v1-cxf.xml b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/META-INF/cxf/authenticators-server-v1-cxf.xml index 0f748ca030..bdb010a761 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/META-INF/cxf/authenticators-server-v1-cxf.xml +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/META-INF/cxf/authenticators-server-v1-cxf.xml @@ -18,6 +18,8 @@ + + diff --git a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/authenticators.yaml b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/authenticators.yaml index c91bc6ab54..f5de9fff0d 100644 --- a/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/authenticators.yaml +++ b/components/org.wso2.carbon.identity.api.server.authenticators/org.wso2.carbon.identity.api.server.authenticators.v1/src/main/resources/authenticators.yaml @@ -118,7 +118,137 @@ paths: $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/ServerError' - + /authenticators/custom: + post: + tags: + - User defined local authenticators + summary: | + Create a new user defined local authenticator. + description: | + This API provides the capability to create a new user defined local authenticator.
+ Permission required:
+ * /permission/admin/manage/custom_authenticator/create
+ Scope required:
+ * internal_custom_authenticator_create
+ operationId: addUserDefinedLocalAuthenticator + responses: + '201': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/Authenticator' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDefinedLocalAuthenticatorCreation' + description: This represents the user defined local authenticator to be created. + required: true + /authenticators/custom/{authenticator-id}: + put: + tags: + - User defined local authenticators + summary: | + Update a user defined local authenticator. + description: | + This API provides the capability to update a user defined local authenticator configurations.
+ Permission required:
+ * /permission/admin/manage/custom_authenticator/update
+ Scope required:
+ * internal_custom_authenticator_update
+ operationId: updateUserDefinedLocalAuthenticator + parameters: + - name: authenticator-id + in: path + description: ID of an authenticator + required: true + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/Authenticator' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserDefinedLocalAuthenticatorUpdate' + description: This represents the user defined local authenticator to be created. + required: true + delete: + tags: + - User defined local authenticators + summary: | + Delete a user defined local authenticator. + description: | + This API provides the capability to delete a user defined local authenticators.
+ Permission required:
+ * /permission/admin/manage/custom_authenticator/delete
+ Scope required:
+ * internal_custom_authenticator_delete
+ operationId: deleteUserDefinedLocalAuthenticator + parameters: + - name: authenticator-id + in: path + description: ID of an authenticator + required: true + schema: + type: string + responses: + '204': + description: Successful response + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' components: parameters: filterQueryParam: @@ -193,6 +323,7 @@ components: id: type: string example: QmFzaWNBdXRoZW50aWNhdG9y + readOnly: true name: type: string example: BasicAuthenticator @@ -207,11 +338,13 @@ components: enum: - SYSTEM - USER + readOnly: true type: type: string enum: - LOCAL - FEDERATED + readOnly: true image: type: string example: basic-authenticator-logo-url @@ -223,9 +356,96 @@ components: items: type: string example: [2FA, MFA] + readOnly: true self: type: string example: /t/carbon.super/api/server/v1/configs/authenticators/eDUwOUNlcnRpZmljYXRlQXV0aGVudGljYXRvcg + UserDefinedLocalAuthenticatorCreation: + description: This represents the configuration for creating the user defined local authenticator. + type: object + properties: + name: + type: string + example: CustomAuthenticator + id: + type: string + example: Q3VzdG9tQXV0aGVudGljYXRvcg== + displayName: + type: string + example: Custom auth + isEnabled: + type: boolean + example: true + authenticationType: + type: string + enum: + - IDENTIFICATION + - VERIFICATION + image: + type: string + example: https://custom-authenticator-logo-url + description: + type: string + example: The user defined custom local authenticator. + endpoint: + $ref: '#/components/schemas/Endpoint' + required: + - name + - displayName + - isEnabled + - endpoint + UserDefinedLocalAuthenticatorUpdate: + description: TThis represents the configuration for updating user defined local authenticator. + type: object + properties: + displayName: + type: string + example: Custom auth + isEnabled: + type: boolean + example: true + image: + type: string + example: https://custom-authenticator-logo-url + description: + type: string + example: The user defined custom local authenticator. + endpoint: + $ref: '#/components/schemas/Endpoint' + required: + - name + - displayName + - isEnabled + - endpoint + Endpoint: + type: object + properties: + uri: + type: string + example: https://abc.com/token + pattern: '^https?://.+' + authentication: + $ref: '#/components/schemas/AuthenticationType' + AuthenticationType: + type: object + required: + - type + - properties + properties: + type: + type: string + enum: + - NONE + - BEARER + - API_KEY + - BASIC + example: BASIC + properties: + type: object + additionalProperties: true + example: + username: "auth_username" + password: "auth_password" ConnectedApps: type: object properties: