Skip to content

Commit

Permalink
Update APIs to support custom authentication management.
Browse files Browse the repository at this point in the history
  • Loading branch information
Thisara-Welmilla committed Nov 12, 2024
1 parent 88ce34f commit 6d3a143
Show file tree
Hide file tree
Showing 3 changed files with 244 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +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 " +
ERROR_CODE_ENDPOINT_PROVIDED_FOR_SYSTEM_AUTH("60039", "No endpoint configuration is allowed " +
"for system defined authenticators.", "No endpoint configuration must be " +
"provided for the system defined federated authenticators %s."),
ERROR_CODE_PROPERTIES_PROVIDED_FOR_USER_AUTH("60040", "No properties are allowed for " +
"user defined authenticators.", "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."),
"No system authenticator found for the provided authenticator Id %s."),

// Server Error starting from 650xx.
ERROR_CODE_ERROR_ADDING_IDP("65002",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.wso2.carbon.identity.api.server.common.error.ErrorResponse;
import org.wso2.carbon.identity.api.server.idp.common.Constants;
import org.wso2.carbon.identity.api.server.idp.common.IdentityProviderServiceHolder;
import org.wso2.carbon.identity.api.server.idp.v1.impl.FederatedAuthenticatorConfigBuilderFactory;
import org.wso2.carbon.identity.api.server.idp.v1.model.AssociationRequest;
import org.wso2.carbon.identity.api.server.idp.v1.model.AssociationResponse;
import org.wso2.carbon.identity.api.server.idp.v1.model.AuthenticationType;
Expand Down Expand Up @@ -1773,43 +1774,31 @@ private void updateFederatedAuthenticatorConfig(IdentityProvider idp, FederatedA
FederatedAuthenticatorConfig defaultAuthConfig = null;
List<FederatedAuthenticatorConfig> fedAuthConfigs = new ArrayList<>();
for (FederatedAuthenticator authenticator : federatedAuthenticators) {
String authenticatorName = getDecodedAuthName(authenticator.getAuthenticatorId());
FederatedAuthenticatorConfig authConfig;
String definedByType = null;
if (authenticator.getDefinedBy() != null) {
definedByType = authenticator.getDefinedBy().toString();
String authenticatorName = getDecodedAuthenticatorName(authenticator.getAuthenticatorId());
String definedByType;
if (isNewFederatedAuthenticator) {
definedByType = resolveDefinedByTypeForCreateFederatedAuthenticator(
authenticator.getDefinedBy().toString()).toString();
} else {
definedByType = resolveDefinedByTypeForUpdateFederatedAuthenticator(authenticatorName).toString();
}

definedByType = resolveDefinedByType(authenticatorName, definedByType, isNewFederatedAuthenticator)
.toString();
if (DefinedByType.SYSTEM.toString().equals(definedByType)) {
authConfig = createSystemDefinedFederatedAuthenticator(authenticatorName,
authenticator.getEndpoint());
List<org.wso2.carbon.identity.api.server.idp.v1.model.Property> 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.");
}
List<Property> properties = authProperties.stream()
.map(propertyToInternal)
.collect(Collectors.toList());
authConfig.setProperties(properties.toArray(new Property[0]));
}
} else {
authConfig = createUserDefinedFederatedAuthenticator(authenticatorName, authenticator.getEndpoint(),
authenticator.getProperties());
validateAuthenticatorProperties(authenticatorName, authenticator.getProperties());
}

authConfig.setName(authenticatorName);
authConfig.setDisplayName(getDisplayNameOfAuthenticator(authConfig.getName()));
authConfig.setEnabled(authenticator.getIsEnabled());
FederatedAuthenticatorConfigBuilderFactory.Builder builder =
new FederatedAuthenticatorConfigBuilderFactory.Builder();
builder.authenticatorName(authenticatorName);
builder.definedByType(definedByType);
builder.enabled(authenticator.getIsEnabled());
builder.displayName(getDisplayNameOfAuthenticator(authenticatorName));
builder.endpoint(authenticator.getEndpoint());
List<Property> properties = authenticator.getProperties().stream().map(propertyToInternal)
.collect(Collectors.toList());
builder.properties(properties);
FederatedAuthenticatorConfig authConfig = builder.build();

fedAuthConfigs.add(authConfig);

if (StringUtils.equals(defaultAuthenticator, authenticator.getAuthenticatorId())) {
Expand Down Expand Up @@ -2858,99 +2847,38 @@ private ProvisioningConnectorConfig createProvisioningConnectorConfig(String out
private FederatedAuthenticatorConfig updateFederatedAuthenticatorConfig(String federatedAuthenticatorId,
FederatedAuthenticatorPUTRequest authenticator) throws IdentityProviderManagementClientException {

String authenticatorName = getDecodedAuthName(federatedAuthenticatorId);
FederatedAuthenticatorConfig authConfig;
String definedByType = null;
if (authenticator.getDefinedBy() != null) {
definedByType = authenticator.getDefinedBy().toString();
}
definedByType = resolveDefinedByType(authenticatorName, definedByType, false).toString();
String authenticatorName = getDecodedAuthenticatorName(federatedAuthenticatorId);
String definedByType = resolveDefinedByTypeForUpdateFederatedAuthenticator(authenticatorName).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<Property> properties = authenticator.getProperties().stream().map(propertyToInternal)
.collect(Collectors.toList());
authConfig.setProperties(properties.toArray(new Property[0]));
} else {
authConfig = createUserDefinedFederatedAuthenticator(authenticatorName, authenticator.getEndpoint(),
authenticator.getProperties());
validateAuthenticatorProperties(authenticatorName, authenticator.getProperties());
}
authConfig.setName(authenticatorName);
authConfig.setDisplayName(getDisplayNameOfAuthenticator(authenticatorName));
authConfig.setEnabled(authenticator.getIsEnabled());

return authConfig;
}

private FederatedAuthenticatorConfig createSystemDefinedFederatedAuthenticator(
String authenticatorName, Endpoint endpoint) throws IdentityProviderManagementClientException {

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 (ApplicationAuthenticatorService.getInstance()
.getFederatedAuthenticatorByName((authenticatorName)) == null) {
Constants.ErrorMessage error = Constants.ErrorMessage.ERROR_CODE_NO_SYSTEM_AUTHENTICATOR_FOUND;
throw new IdentityProviderManagementClientException(error.getCode(), error.getDescription());
}

FederatedAuthenticatorConfig authConfig = new FederatedAuthenticatorConfig();
authConfig.setDefinedByType(DefinedByType.SYSTEM);
FederatedAuthenticatorConfigBuilderFactory.Builder builder = new FederatedAuthenticatorConfigBuilderFactory
.Builder();
builder.authenticatorName(authenticatorName);
builder.definedByType(definedByType);
builder.enabled(authenticator.getIsEnabled());
builder.displayName(getDisplayNameOfAuthenticator(authenticatorName));
builder.endpoint(authenticator.getEndpoint());
List<Property> properties = authenticator.getProperties().stream().map(propertyToInternal)
.collect(Collectors.toList());
builder.properties(properties);

return authConfig;
return builder.build();
}

private UserDefinedFederatedAuthenticatorConfig createUserDefinedFederatedAuthenticator(
String authenticatorName, Endpoint endpoint, List<org.wso2.carbon.identity.api.server.idp.v1.model.Property>
properties) throws IdentityProviderManagementClientException {
private DefinedByType resolveDefinedByTypeForCreateFederatedAuthenticator(String definedByType) {

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));
/* For new federated authenticators:
If 'definedByType' is not null, use the value provided in the request payload. If not, default to SYSTEM. */
if (definedByType != null) {
return DefinedByType.valueOf(definedByType);
}

UserDefinedFederatedAuthenticatorConfig userDefinedAuthConfig = new UserDefinedFederatedAuthenticatorConfig();
userDefinedAuthConfig.setDefinedByType(DefinedByType.USER);

UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder endpointConfigBuilder =
new UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder();
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;
return DefinedByType.SYSTEM;
}

private DefinedByType resolveDefinedByType(
String authenticatorName, String definedByType, boolean isNewFederatedAuthenticator) {
private DefinedByType resolveDefinedByTypeForUpdateFederatedAuthenticator(String authenticatorName) {

/* For new federated authenticators:
If 'definedByType' is not null, use the value provided in the request payload. If not, default to SYSTEM. */
if (isNewFederatedAuthenticator) {
if (definedByType != null) {
return DefinedByType.valueOf(definedByType);
} else {
return DefinedByType.SYSTEM;
}
}
/* For existing federated authenticators, disregard any value provided in the request payload.
Instead, resolve and retrieve the 'definedBy' type of the corresponding existing authenticator.
If the authenticator config is present in the ApplicationAuthenticatorService list, return its type,
Expand Down Expand Up @@ -3182,8 +3110,8 @@ private void resolveEndpointConfiguration(FederatedAuthenticator authenticator,
endpoint.setUri(endpointConfig.getEndpointConfig().getUri());
authenticator.setEndpoint(endpoint);
} catch (ClassCastException e) {
throw new IdentityProviderManagementServerException("Error occurred while resolving endpoint " +
"configuration of the authenticator.", e);
throw new IdentityProviderManagementServerException(String.format("Error occurred while resolving" +
" endpoint configuration of the authenticator %s.", authenticator.getName()), e);
}
}

Expand Down Expand Up @@ -3955,7 +3883,7 @@ private void validateSystemReservedIDP(String idpName) throws IdentityProviderMa
}
}

private String getDecodedAuthName(String authId) throws IdentityProviderManagementClientException {
private String getDecodedAuthenticatorName(String authId) throws IdentityProviderManagementClientException {

try {
return base64URLDecode(authId);
Expand All @@ -3965,4 +3893,22 @@ private String getDecodedAuthName(String authId) throws IdentityProviderManageme
String.format(error.getDescription(), authId));
}
}

private void validateAuthenticatorProperties(String authenticatorName,
List<org.wso2.carbon.identity.api.server.idp.v1.model.Property> properties)
throws IdentityProviderManagementClientException {

if (IdentityApplicationConstants.Authenticator.SAML2SSO.FED_AUTH_NAME.equals(authenticatorName)) {
validateSamlMetadata(properties);
}
if (IdentityApplicationConstants.Authenticator.OIDC.FED_AUTH_NAME.equals(authenticatorName)) {
validateDuplicateOpenIDConnectScopes(properties);
validateDefaultOpenIDConnectScopes(properties);
}

if (!areAllDistinct(properties)) {
Constants.ErrorMessage error = Constants.ErrorMessage.ERROR_CODE_INVALID_INPUT;
throw new IdentityProviderManagementClientException(error.getCode(), error.getDescription());
}
}
}
Loading

0 comments on commit 6d3a143

Please sign in to comment.