diff --git a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.common/src/main/java/org/wso2/carbon/identity/api/server/idp/common/Constants.java b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.common/src/main/java/org/wso2/carbon/identity/api/server/idp/common/Constants.java index 7d88182eb5..c431dfad97 100644 --- a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.common/src/main/java/org/wso2/carbon/identity/api/server/idp/common/Constants.java +++ b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.common/src/main/java/org/wso2/carbon/identity/api/server/idp/common/Constants.java @@ -146,6 +146,18 @@ public enum ErrorMessage { ERROR_CODE_ERROR_LISTING_TRUSTED_TOKEN_ISSUERS("60021", "Unable to list existing trusted token issuers.", "Server encountered an error while listing the trusted token issuers."), + ERROR_CODE_ENDPOINT_PROVIDED_FOR_SYSTEM_AUTH("60039", "Endpoint provided for the system " + + "defined federated authenticator", "No endpoint configuration must be provided for " + + "the system defined federated authenticators %s."), + ERROR_CODE_PROPERTIES_PROVIDED_FOR_USER_AUTH("60040", "Properties provided for the user " + + "defined federated authenticator", "No properties must be provided for the user defined " + + "federated authenticators %s."), + ERROR_CODE_NO_ENDPOINT_PROVIDED("60041", "No endpoint provided.", "Endpoint " + + "configuration must be provided for the user defined federated authenticators %s."), + ERROR_CODE_NON_DECODABLE_AUTH_ID("60042", "Non-decodable authenticator ID.", + "Unable to decode the provided authenticator ID %s."), + ERROR_CODE_NO_SYSTEM_AUTHENTICATOR_FOUND("60043", "No system authenticator found.", + "No system authenticator found for the provided authenticator Id."), // Server Error starting from 650xx. ERROR_CODE_ERROR_ADDING_IDP("65002", diff --git a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/gen/java/org/wso2/carbon/identity/api/server/idp/v1/model/Endpoint.java b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/gen/java/org/wso2/carbon/identity/api/server/idp/v1/model/Endpoint.java index 477bb8c8ad..9ce553d2ac 100644 --- a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/gen/java/org/wso2/carbon/identity/api/server/idp/v1/model/Endpoint.java +++ b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/gen/java/org/wso2/carbon/identity/api/server/idp/v1/model/Endpoint.java @@ -44,9 +44,11 @@ public Endpoint uri(String uri) { return this; } - @ApiModelProperty(example = "https://abc.com/token", value = "") + @ApiModelProperty(example = "https://abc.com/token", required = true, value = "") @JsonProperty("uri") - @Valid @Pattern(regexp="^https?://.+") + @Valid + @NotNull(message = "Property uri cannot be null.") + @Pattern(regexp="^https?://.+") public String getUri() { return uri; } @@ -62,9 +64,11 @@ public Endpoint authentication(AuthenticationType authentication) { return this; } - @ApiModelProperty(value = "") + @ApiModelProperty(required = true, value = "") @JsonProperty("authentication") @Valid + @NotNull(message = "Property authentication cannot be null.") + public AuthenticationType getAuthentication() { return authentication; } diff --git a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/java/org/wso2/carbon/identity/api/server/idp/v1/core/ServerIdpManagementService.java b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/java/org/wso2/carbon/identity/api/server/idp/v1/core/ServerIdpManagementService.java index 45f99e9052..ec4848cf03 100644 --- a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/java/org/wso2/carbon/identity/api/server/idp/v1/core/ServerIdpManagementService.java +++ b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/java/org/wso2/carbon/identity/api/server/idp/v1/core/ServerIdpManagementService.java @@ -34,8 +34,6 @@ import org.apache.cxf.jaxrs.ext.search.PrimitiveStatement; import org.apache.cxf.jaxrs.ext.search.SearchCondition; import org.apache.cxf.jaxrs.ext.search.SearchContext; -import org.wso2.carbon.identity.action.management.model.AuthProperty; -import org.wso2.carbon.identity.action.management.model.EndpointConfig; import org.wso2.carbon.identity.api.server.common.ContextLoader; import org.wso2.carbon.identity.api.server.common.FileContent; import org.wso2.carbon.identity.api.server.common.Util; @@ -1764,7 +1762,8 @@ private MetaOutboundConnector createMetaOutboundConnector(ProvisioningConnectorC } private void updateFederatedAuthenticatorConfig(IdentityProvider idp, FederatedAuthenticatorRequest - federatedAuthenticatorRequest, boolean isNewFederatedAuthenticator) { + federatedAuthenticatorRequest, boolean isNewFederatedAuthenticator) + throws IdentityProviderManagementClientException { if (federatedAuthenticatorRequest != null) { List federatedAuthenticators = federatedAuthenticatorRequest.getAuthenticators(); @@ -1772,34 +1771,43 @@ private void updateFederatedAuthenticatorConfig(IdentityProvider idp, FederatedA FederatedAuthenticatorConfig defaultAuthConfig = null; List fedAuthConfigs = new ArrayList<>(); for (FederatedAuthenticator authenticator : federatedAuthenticators) { - FederatedAuthenticatorConfig authConfig = new FederatedAuthenticatorConfig(); - authConfig.setName(base64URLDecode(authenticator.getAuthenticatorId())); - authConfig.setDisplayName(getDisplayNameOfAuthenticator(authConfig.getName())); - authConfig.setEnabled(authenticator.getIsEnabled()); - + String authenticatorName = getDecodedAuthName(authenticator.getAuthenticatorId()); + FederatedAuthenticatorConfig authConfig; String definedByType = null; if (authenticator.getDefinedBy() != null) { definedByType = authenticator.getDefinedBy().toString(); } - authConfig.setDefinedByType(resolveDefinedByType(authConfig.getName(), - definedByType, isNewFederatedAuthenticator)); - List authProperties = - authenticator.getProperties(); - if (IdentityApplicationConstants.Authenticator.SAML2SSO.FED_AUTH_NAME.equals(authConfig.getName())) { - validateSamlMetadata(authProperties); - } - if (authProperties != null) { - if (!areAllDistinct(authProperties)) { - throw handleException(Response.Status.BAD_REQUEST, - Constants.ErrorMessage.ERROR_CODE_INVALID_INPUT, " Duplicate properties are found in " + - "the request."); + definedByType = resolveDefinedByType(authenticatorName, definedByType, isNewFederatedAuthenticator) + .toString(); + if (DefinedByType.SYSTEM.toString().equals(definedByType)) { + authConfig = createSystemDefinedFederatedAuthenticator(authenticatorName, + authenticator.getEndpoint()); + List authProperties = + authenticator.getProperties(); + if (IdentityApplicationConstants.Authenticator.SAML2SSO.FED_AUTH_NAME + .equals(authConfig.getName())) { + validateSamlMetadata(authProperties); } - List properties = authProperties.stream() - .map(propertyToInternal) - .collect(Collectors.toList()); - authConfig.setProperties(properties.toArray(new Property[0])); + if (authProperties != null) { + if (!areAllDistinct(authProperties)) { + throw handleException(Response.Status.BAD_REQUEST, + Constants.ErrorMessage.ERROR_CODE_INVALID_INPUT, " Duplicate properties are found" + + " in the request."); + } + List properties = authProperties.stream() + .map(propertyToInternal) + .collect(Collectors.toList()); + authConfig.setProperties(properties.toArray(new Property[0])); + } + } else { + authConfig = createUserDefinedFederatedAuthenticator(authenticatorName, authenticator.getEndpoint(), + authenticator.getProperties()); } + + authConfig.setName(authenticatorName); + authConfig.setDisplayName(getDisplayNameOfAuthenticator(authConfig.getName())); + authConfig.setEnabled(authenticator.getIsEnabled()); fedAuthConfigs.add(authConfig); if (StringUtils.equals(defaultAuthenticator, authenticator.getAuthenticatorId())) { @@ -2085,7 +2093,8 @@ private void updateGroups(IdentityProvider idp, List groups) { return apiProperty; }; - private IdentityProvider createIDP(IdentityProviderPOSTRequest identityProviderPOSTRequest) { + private IdentityProvider createIDP(IdentityProviderPOSTRequest identityProviderPOSTRequest) + throws IdentityProviderManagementClientException { String idpJWKSUri = null; IdentityProvider idp = new IdentityProvider(); @@ -2845,20 +2854,30 @@ private ProvisioningConnectorConfig createProvisioningConnectorConfig(String out * @return Federated authenticator config of the specified ID. */ private FederatedAuthenticatorConfig updateFederatedAuthenticatorConfig(String federatedAuthenticatorId, - FederatedAuthenticatorPUTRequest - authenticator) { + FederatedAuthenticatorPUTRequest authenticator) throws IdentityProviderManagementClientException { - String authenticatorName = base64URLDecode(federatedAuthenticatorId); + String authenticatorName = getDecodedAuthName(federatedAuthenticatorId); FederatedAuthenticatorConfig authConfig; - DefinedByType definedByType = null; + String definedByType = null; if (authenticator.getDefinedBy() != null) { definedByType = authenticator.getDefinedBy().toString(); } - definedByType = resolveDefinedByType(authenticatorName, definedByType.toString(), false); - if (definedByType == DefinedByType.SYSTEM) { - authConfig = createSystemDefinedFederatedAuthenticator(authenticator, authenticatorName); + definedByType = resolveDefinedByType(authenticatorName, definedByType, false).toString(); + if (DefinedByType.SYSTEM.toString().equals(definedByType)) { + authConfig = createSystemDefinedFederatedAuthenticator(authenticatorName, authenticator.getEndpoint()); + if (IdentityApplicationConstants.Authenticator.SAML2SSO.FED_AUTH_NAME.equals(authenticatorName)) { + validateSamlMetadata(authenticator.getProperties()); + } + if (IdentityApplicationConstants.Authenticator.OIDC.FED_AUTH_NAME.equals(authenticatorName)) { + validateDuplicateOpenIDConnectScopes(authenticator.getProperties()); + validateDefaultOpenIDConnectScopes(authenticator.getProperties()); + } + List properties = authenticator.getProperties().stream().map(propertyToInternal) + .collect(Collectors.toList()); + authConfig.setProperties(properties.toArray(new Property[0])); } else { - authConfig = createUserDefinedFederatedAuthenticator(authenticator); + authConfig = createUserDefinedFederatedAuthenticator(authenticatorName, authenticator.getEndpoint(), + authenticator.getProperties()); } authConfig.setName(authenticatorName); authConfig.setDisplayName(getDisplayNameOfAuthenticator(authenticatorName)); @@ -2868,38 +2887,53 @@ private FederatedAuthenticatorConfig updateFederatedAuthenticatorConfig(String f } private FederatedAuthenticatorConfig createSystemDefinedFederatedAuthenticator( - FederatedAuthenticatorPUTRequest authenticator, String authenticatorName) { + String authenticatorName, Endpoint endpoint) throws IdentityProviderManagementClientException { - FederatedAuthenticatorConfig authConfig = new FederatedAuthenticatorConfig(); - authConfig.setDefinedByType(DefinedByType.SYSTEM); - - List authProperties = authenticator.getProperties(); - if (IdentityApplicationConstants.Authenticator.SAML2SSO.FED_AUTH_NAME.equals(authenticatorName)) { - validateSamlMetadata(authProperties); + if (endpoint != null) { + Constants.ErrorMessage error = Constants.ErrorMessage.ERROR_CODE_ENDPOINT_PROVIDED_FOR_SYSTEM_AUTH; + throw new IdentityProviderManagementClientException(error.getCode(), + String.format(error.getDescription(), authenticatorName)); } - if (IdentityApplicationConstants.Authenticator.OIDC.FED_AUTH_NAME.equals(authenticatorName)) { - validateDuplicateOpenIDConnectScopes(authProperties); - validateDefaultOpenIDConnectScopes(authProperties); + + if (ApplicationAuthenticatorService.getInstance() + .getFederatedAuthenticatorByName((authenticatorName)) == null) { + Constants.ErrorMessage error = Constants.ErrorMessage.ERROR_CODE_NO_SYSTEM_AUTHENTICATOR_FOUND; + throw new IdentityProviderManagementClientException(error.getCode(), error.getDescription()); } - List properties = authProperties.stream().map(propertyToInternal).collect(Collectors.toList()); - authConfig.setProperties(properties.toArray(new Property[0])); + + FederatedAuthenticatorConfig authConfig = new FederatedAuthenticatorConfig(); + authConfig.setDefinedByType(DefinedByType.SYSTEM); return authConfig; } private UserDefinedFederatedAuthenticatorConfig createUserDefinedFederatedAuthenticator( - FederatedAuthenticatorPUTRequest authenticator) { + String authenticatorName, Endpoint endpoint, List + properties) throws IdentityProviderManagementClientException { + + if (properties == null || !properties.isEmpty()) { + Constants.ErrorMessage error = Constants.ErrorMessage.ERROR_CODE_PROPERTIES_PROVIDED_FOR_USER_AUTH; + throw new IdentityProviderManagementClientException(error.getCode(), + String.format(error.getDescription(), authenticatorName)); + } + + if (endpoint == null || endpoint.getUri() == null || endpoint.getAuthentication() == null) { + Constants.ErrorMessage error = Constants.ErrorMessage.ERROR_CODE_NO_ENDPOINT_PROVIDED; + throw new IdentityProviderManagementClientException(error.getCode(), + String.format(error.getDescription(), authenticatorName)); + } UserDefinedFederatedAuthenticatorConfig userDefinedAuthConfig = new UserDefinedFederatedAuthenticatorConfig(); userDefinedAuthConfig.setDefinedByType(DefinedByType.USER); UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder endpointConfigBuilder = new UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder(); - endpointConfigBuilder.uri(authenticator.getEndpoint().getUri()); - endpointConfigBuilder.authenticationType(authenticator.getEndpoint().getAuthentication().getType().toString()); - endpointConfigBuilder.authenticationProperties(authenticator.getEndpoint().getAuthentication().getProperties() + endpointConfigBuilder.uri(endpoint.getUri()); + endpointConfigBuilder.authenticationType(endpoint.getAuthentication().getType().toString()); + endpointConfigBuilder.authenticationProperties(endpoint.getAuthentication().getProperties() .entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().toString()))); + userDefinedAuthConfig.setEndpointConfig(endpointConfigBuilder.build()); return userDefinedAuthConfig; } @@ -3136,20 +3170,14 @@ private void resolveEndpointConfiguration(FederatedAuthenticator authenticator, try { UserDefinedFederatedAuthenticatorConfig userDefinedConfig = (UserDefinedFederatedAuthenticatorConfig) config; - EndpointConfig endpointConfig = userDefinedConfig.getEndpointConfig().getEndpointConfig(); + UserDefinedAuthenticatorEndpointConfig endpointConfig = userDefinedConfig.getEndpointConfig(); AuthenticationType authenticationType = new AuthenticationType(); - authenticationType.setType(AuthenticationType.TypeEnum.fromValue(endpointConfig + authenticationType.setType(AuthenticationType.TypeEnum.fromValue(endpointConfig.getEndpointConfig() .getAuthentication().getType().toString())); - Map authenticatorProperties = new HashMap<>(); - for (AuthProperty prop: endpointConfig.getAuthentication().getProperties()) { - authenticatorProperties.put(prop.getName(), prop.getValue()); - } - authenticationType.setProperties(authenticatorProperties); Endpoint endpoint = new Endpoint(); - endpoint.setAuthentication(authenticationType); - endpoint.setUri(userDefinedConfig.getEndpointConfig().getEndpointConfig().getUri()); + endpoint.setUri(endpointConfig.getEndpointConfig().getUri()); authenticator.setEndpoint(endpoint); } catch (ClassCastException e) { throw new IdentityProviderManagementServerException("Error occurred while resolving endpoint " + @@ -3924,4 +3952,15 @@ private void validateSystemReservedIDP(String idpName) throws IdentityProviderMa "a system reserved name.", idpName)); } } + + private String getDecodedAuthName(String authId) throws IdentityProviderManagementClientException { + + try { + return base64URLDecode(authId); + } catch (IllegalArgumentException e) { + Constants.ErrorMessage error = Constants.ErrorMessage.ERROR_CODE_NON_DECODABLE_AUTH_ID; + throw new IdentityProviderManagementClientException(error.getCode(), + String.format(error.getDescription(), authId)); + } + } } diff --git a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/resources/idp.yaml b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/resources/idp.yaml index 53d1d0ee1b..875aa8ad8c 100644 --- a/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/resources/idp.yaml +++ b/components/org.wso2.carbon.identity.api.server.idp/org.wso2.carbon.identity.api.server.idp.v1/src/main/resources/idp.yaml @@ -2825,7 +2825,6 @@ components: items: $ref: '#/components/schemas/MetaProperty' endpoint: - endpoint: $ref: '#/components/schemas/Endpoint' FederatedAuthenticatorRequest: type: object @@ -2884,6 +2883,9 @@ components: $ref: '#/components/schemas/Endpoint' Endpoint: type: object + required: + - uri + - authentication properties: uri: type: string