diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/CustomIdPSuccessTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/CustomIdPSuccessTest.java new file mode 100644 index 00000000000..26be7111269 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/CustomIdPSuccessTest.java @@ -0,0 +1,424 @@ +package org.wso2.identity.integration.test.rest.api.server.idp.v1; + +import io.restassured.RestAssured; +import io.restassured.response.Response; +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpStatus; +import org.testng.annotations.*; +import org.wso2.carbon.automation.engine.context.TestUserMode; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.model.AuthenticationType; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.model.Endpoint; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.model.FederatedAuthenticatorRequest; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.util.UserDefinedAuthenticatorPayload; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsNull.nullValue; +import static org.testng.Assert.assertNotNull; + +public class CustomIdPSuccessTest extends IdPTestBase { + + private String idPId; + private UserDefinedAuthenticatorPayload userDefinedAuthenticatorPayload; + private String idpCreatePayload; + + private static final String FEDERATED_AUTHENTICATOR_ID = ""; + private static final String FEDERATED_AUTHENTICATOR = "\"\""; + + @Factory(dataProvider = "restAPIUserConfigProvider") + public CustomIdPSuccessTest(TestUserMode userMode) throws Exception { + + super.init(userMode); + this.context = isServer; + this.authenticatingUserName = context.getContextTenant().getTenantAdmin().getUserName(); + this.authenticatingCredential = context.getContextTenant().getTenantAdmin().getPassword(); + this.tenant = context.getContextTenant().getDomain(); + } + + @BeforeClass(alwaysRun = true) + public void init() throws IOException { + + super.testInit(API_VERSION, swaggerDefinition, tenant); + userDefinedAuthenticatorPayload = createUserDefinedAuthenticatorPayload(); + idpCreatePayload = readResource("add-idp.json"); + + } + + private UserDefinedAuthenticatorPayload createUserDefinedAuthenticatorPayload() { + + UserDefinedAuthenticatorPayload userDefinedAuthenticatorPayload = new UserDefinedAuthenticatorPayload(); + userDefinedAuthenticatorPayload.setIsEnabled(true); + userDefinedAuthenticatorPayload.setAuthenticatorId("custom-idp"); + userDefinedAuthenticatorPayload.setName("CustomIdP"); + userDefinedAuthenticatorPayload.setDefinedBy(FederatedAuthenticatorRequest.DefinedByEnum.USER.toString()); + + Endpoint endpoint = new Endpoint(); + endpoint.setUri("https://localhost:9443/oauth2/token"); + AuthenticationType authenticationType = new AuthenticationType(); + authenticationType.setType(AuthenticationType.TypeEnum.BASIC); + Map properties = new HashMap<>(); + properties.put("username", "testUser"); + properties.put("password", "testPassword"); + userDefinedAuthenticatorPayload.setEndpoint(endpoint); + + return userDefinedAuthenticatorPayload; + } + + @AfterClass(alwaysRun = true) + public void testConclude() { + + super.conclude(); + } + + @BeforeMethod(alwaysRun = true) + public void testInit() { + + RestAssured.basePath = basePath; + } + + @AfterMethod(alwaysRun = true) + public void testFinish() { + + RestAssured.basePath = StringUtils.EMPTY; + } + + @DataProvider(name = "restAPIUserConfigProvider") + public static Object[][] restAPIUserConfigProvider() { + + return new Object[][]{ + {TestUserMode.SUPER_TENANT_ADMIN}, + {TestUserMode.TENANT_ADMIN} + }; + } + + @Test + public void testAddIdP() throws IOException { + + userDefinedAuthenticatorPayload.convertToJasonPayload(); + String body; + body = idpCreatePayload.replace(FEDERATED_AUTHENTICATOR_ID, + userDefinedAuthenticatorPayload.getAuthenticatorId()); + body = body.replace(FEDERATED_AUTHENTICATOR, userDefinedAuthenticatorPayload.convertToJasonPayload()); + Response response = getResponseOfPost(IDP_API_BASE_PATH, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_CREATED) + .header(HttpHeaders.LOCATION, notNullValue()); + + String location = response.getHeader(HttpHeaders.LOCATION); + assertNotNull(location); + idPId = location.substring(location.lastIndexOf("/") + 1); + assertNotNull(idPId); + } + + + + /* + @Test(dependsOnMethods = {"testAddIdP"}) + public void testGetIdP() throws IOException { + + Response response = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("id", equalTo(idPId)) + .body("name", equalTo("Google")) + .body("description", equalTo("IDP for Google Federation")) + .body("isEnabled", equalTo(true)) + .body("isPrimary", equalTo(false)) + .body("image", equalTo("google-logo-url")) + .body("isFederationHub", equalTo(false)) + .body("homeRealmIdentifier", equalTo("localhost")) + .body("alias", equalTo("https://localhost:9444/oauth2/token")); + } + + @Test(dependsOnMethods = {"testGetIdP"}) + public void testGetIdPs() throws Exception { + + String baseIdentifier = "identityProviders.find{ it.id == '" + idPId + "' }."; + Response response = getResponseOfGet(IDP_API_BASE_PATH); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body(baseIdentifier + "name", equalTo("Google")) + .body(baseIdentifier + "description", equalTo("IDP for Google Federation")) + .body(baseIdentifier + "isEnabled", equalTo(true)) + .body(baseIdentifier + "image", equalTo("google-logo-url")) + .body(baseIdentifier + "self", equalTo(getTenantedRelativePath( + "/api/server/v1/identity-providers/" + idPId, + context.getContextTenant().getDomain()))); + } + + @Test(dependsOnMethods = {"testGetIdPs"}) + public void testGetIdPsWithRequiredAttribute() throws Exception { + + String baseIdentifier = "identityProviders.find{ it.id == '" + idPId + "' }."; + Map requiredAttributeParam = new HashMap<>(); + requiredAttributeParam.put("requiredAttributes", "homeRealmIdentifier"); + Response response = + getResponseOfGetWithQueryParams(IDP_API_BASE_PATH, requiredAttributeParam); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body(baseIdentifier + "name", equalTo("Google")) + .body(baseIdentifier + "description", equalTo("IDP for Google Federation")) + .body(baseIdentifier + "isEnabled", equalTo(true)) + .body(baseIdentifier + "image", equalTo("google-logo-url")) + .body(baseIdentifier + "self", equalTo(getTenantedRelativePath( + "/api/server/v1/identity-providers/" + idPId, + context.getContextTenant().getDomain()))) + .body(baseIdentifier + "homeRealmIdentifier", equalTo("localhost")); + } + + @Test(dependsOnMethods = {"testGetIdPsWithRequiredAttribute"}) + public void testGetIdPFederatedAuthenticators() throws Exception { + + String baseIdentifier = + "authenticators.find{ it.authenticatorId == '" + SAMPLE_FEDERATED_AUTHENTICATOR_ID + "' }."; + Response response = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + + IDP_FEDERATED_AUTHENTICATORS_PATH); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body(baseIdentifier + "name", equalTo("GoogleOIDCAuthenticator")) + .body(baseIdentifier + "isEnabled", equalTo(true)) + .body(baseIdentifier + "self", equalTo(getTenantedRelativePath( + "/api/server/v1/identity-providers/" + idPId + "/federated-authenticators/" + + SAMPLE_FEDERATED_AUTHENTICATOR_ID, context.getContextTenant().getDomain()))); + } + + @Test(dependsOnMethods = {"testGetIdPFederatedAuthenticators"}) + public void testUpdateIdPFederatedAuthenticator() throws IOException { + + String body = readResource("update-idp-federated-authenticator.json"); + Response response = getResponseOfPut( + IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + IDP_FEDERATED_AUTHENTICATORS_PATH + + PATH_SEPARATOR + SAMPLE_FEDERATED_AUTHENTICATOR_ID, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("definedBy", equalTo("SYSTEM")); + } + + @Test(dependsOnMethods = {"testUpdateIdPFederatedAuthenticator"}) + public void testGetIdPFederatedAuthenticator() throws IOException { + + Response response = getResponseOfGet( + IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + IDP_FEDERATED_AUTHENTICATORS_PATH + + PATH_SEPARATOR + SAMPLE_FEDERATED_AUTHENTICATOR_ID); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("name", equalTo("GoogleOIDCAuthenticator")) + .body("isEnabled", equalTo(true)) + .body("isDefault", equalTo(true)) + .body("properties", notNullValue()) + .body("definedBy", equalTo("SYSTEM")) + .body("properties.find{ it.key == 'ClientId' }.value", equalTo + ("165474950684-7mvqd8m6hieb8mdnffcarnku2aua0tpl.apps.googleusercontent.com")) + .body("properties.find{ it.key == 'ClientSecret' }.value", equalTo("testclientsecret")) + .body("properties.find{ it.key == 'callbackUrl' }.value", equalTo + ("https://mydomain1.com:9443/commonauth")) + .body("properties.find{ it.key == 'AdditionalQueryParameters' }.value", equalTo("scope=openid email" + + " profile")); + } + + @Test(dependsOnMethods = {"testGetIdPOutboundConnector"}) + public void testUpdateIdPClaims() throws IOException { + + String body = readResource("update-idp-claims.json"); + Response response = getResponseOfPut(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + + IDP_CLAIMS_PATH, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("userIdClaim", notNullValue()) + .body("userIdClaim.uri", equalTo("country")) + .body("roleClaim.uri", equalTo("roles")); + } + + @Test(dependsOnMethods = {"testUpdateIdPClaims"}) + public void testGetIdPClaims() throws IOException { + + Response response = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + + IDP_CLAIMS_PATH); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("userIdClaim", notNullValue()) + .body("userIdClaim.uri", equalTo("country")) + .body("roleClaim", notNullValue()) + .body("roleClaim.uri", equalTo("roles")) + .body("mappings", notNullValue()) + .body("mappings[0].idpClaim", equalTo("country")) + .body("mappings[0].localClaim.id", equalTo("aHR0cDovL3dzbzIub3JnL2NsYWltcy91c2VybmFtZQ")) + .body("mappings[0].localClaim.uri", equalTo("http://wso2.org/claims/username")) + .body("mappings[0].localClaim.displayName", equalTo("Username")) + .body("mappings[1].idpClaim", equalTo("roles")) + .body("mappings[1].localClaim.id", equalTo("aHR0cDovL3dzbzIub3JnL2NsYWltcy9yb2xlcw")) + .body("mappings[1].localClaim.uri", equalTo("http://wso2.org/claims/roles")) + .body("mappings[1].localClaim.displayName", equalTo("Roles")) + .body("provisioningClaims", notNullValue()) + .body("provisioningClaims[0].claim.uri", equalTo("country")) + .body("provisioningClaims[0].defaultValue", equalTo("sathya")); + } + + @Test(dependsOnMethods = {"testGetIdPClaims"}) + public void testUpdateIdPRoles() throws IOException { + + String body = readResource("update-idp-roles.json"); + Response response = getResponseOfPut(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + + IDP_ROLES_PATH, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("mappings", notNullValue()) + .body("mappings[0].idpRole", equalTo("google-admin")); + } + + @Test(dependsOnMethods = {"testUpdateIdPRoles"}) + public void testGetIdPRoles() throws IOException { + + Response response = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + + IDP_ROLES_PATH); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("mappings", notNullValue()) + .body("mappings[0].idpRole", equalTo("google-admin")) + .body("mappings[0].localRole", equalTo("Internal/admin")) + .body("outboundProvisioningRoles", notNullValue()) + .body("outboundProvisioningRoles[0]", equalTo("Internal/admin")); + } + + @Test(dependsOnMethods = {"testGetIdPRoles"}) + public void testUpdateIdPJIT() throws IOException { + + String body = readResource("update-idp-jit.json"); + Response response = + getResponseOfPut(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + IDP_PROVISIONING_PATH + + PATH_SEPARATOR + IDP_JIT_PATH, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("isEnabled", equalTo(false)); + } + + @Test(dependsOnMethods = {"testUpdateIdPJIT"}) + public void testGetIdPJIT() throws IOException { + + Response response = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId + PATH_SEPARATOR + + IDP_PROVISIONING_PATH + PATH_SEPARATOR + IDP_JIT_PATH); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("isEnabled", equalTo(false)) + .body("scheme", equalTo("PROVISION_SILENTLY")) + .body("userstore", equalTo("PRIMARY")); + } + + @Test(dependsOnMethods = {"testGetIdPJIT"}) + public void testPatchIdP() throws IOException { + + String body = readResource("patch-idp-home-realm.json"); + Response response = getResponseOfPatch(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("homeRealmIdentifier", equalTo("google")); + + // Test patch ADD operation for JWKS URI property. + body = readResource("patch-add-jwks-uri.json"); + response = getResponseOfPatch(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("certificate.jwksUri", equalTo("http://SAMPLE.JWKS.URI/")) + .body("certificate.certificates", nullValue()); + + // Test patch REMOVE operation for JWKS URI property. + body = readResource("patch-remove-jwks-uri.json"); + response = getResponseOfPatch(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("certificate.jwksUri", nullValue()); + + // Test patch ADD operation for certificates. + body = readResource("patch-add-certificate.json"); + response = getResponseOfPatch(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("certificate.certificates[0]", equalTo("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR" + + "zRENDQXBpZ0F3SUJBZ0lKQUs0eml2ckVsYzBJTUEwR0NTcUdTSWIzRFFFQkN3VUFNSUdETVJFd0R3WUQKVlFRRERBaE" + + "NkV1JrYUdsdFlURUxNQWtHQTFVRUJoTUNVMHd4RURBT0JnTlZCQWdNQjFkbGMzUmxjbTR4RURBTwpCZ05WQkFjTUIwT" + + "nZiRzl0WW04eERUQUxCZ05WQkFvTUJGZFRUekl4Q3pBSkJnTlZCQXNNQWxGQk1TRXdId1lKCktvWklodmNOQVFrQkZo" + + "SmlkV1JrYUdsdFlYVkFkM052TWk1amIyMHdJQmNOTVRrd056RTJNRFF5TXpFd1doZ1AKTXpBeE9ERXhNVFl3TkRJek1" + + "UQmFNSUdETVJFd0R3WURWUVFEREFoQ2RXUmthR2x0WVRFTE1Ba0dBMVVFQmhNQwpVMHd4RURBT0JnTlZCQWdNQjFkbG" + + "MzUmxjbTR4RURBT0JnTlZCQWNNQjBOdmJHOXRZbTh4RFRBTEJnTlZCQW9NCkJGZFRUekl4Q3pBSkJnTlZCQXNNQWxGQ" + + "k1TRXdId1lKS29aSWh2Y05BUWtCRmhKaWRXUmthR2x0WVhWQWQzTnYKTWk1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFF" + + "QkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDcFo3V09VMTZpeGpiQwpiWGR3R3JhTW5xbmxnb2kzMDN5aVFxbHAySzlWTmZ" + + "HT21nTlFhdFdlbjB0MVVWcjYxd0Y4eVlHaDJyc1lnbithCjhwYXVmUVVQQ1laeFRFR1FpT2RPZ0RNcE5tWW82ZHU2K2" + + "MvenJqcHNncGh5SHIxNEZPVHAxaVRDSXBmanVwVjEKd1BUeXJveURySGRvMkpuOHI3V3F1cklJVTRBYllBN2NrdVVqL" + + "0tqYUovTTZrZitwRFd5SVJvaDBKTFJlWWM4UQp5bmhYcjdrQWp5RnFqNitnWndBYkh4ckhrckVzYTJoVjQ0UFJXWjFQ" + + "UERxTCswVU8veE1hQW5udndsdGd4QlVpCkhLUTFXWDVwdVVPaC9kQTQ5b0RsbEpraHpxd2d5eDQxc1FYbFNhVmdKakl" + + "UZVdSQmdvNnh6ajNmd3VvenBGS1gKbzRaeXBITDNBZ01CQUFHakl6QWhNQjhHQTFVZEVRUVlNQmFDQkhkemJ6S0NDSG" + + "R6YnpJdVkyOXRnZ1IzYzI4eQpNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJTSzBKa1pyYlpvYmRDNHhZSG1IcnlVb" + + "kZVbkZZWUFvZmc0TFVGCkJRbWxDY0NKR0ZwR1BtN2ZDWHM0Y0h4Z0hPVTN5SkhtQ2pYaU9FRTc2dzhIU0NRcVhkNmRO" + + "SEwxRkxtN0pqQTUKTEZmbHhiWXNOcmVVNVpJTmREVGZvWmxSSXR0Mkd4MlpIa3pjQVRJZm1yUFNwODV2WDhGem1mbTN" + + "BVTVpM3FXZQo4a2YyZk5nQjlMbE5XRFk1V09paVlHUWMrRk13WWdLcDJkNGM3dzMrWnRTUXJWRy9YdGpqYTJYV09Xdm" + + "1sV3dLCnB4b3pyNjIvTTdUUmVkc3hJNU90bzJvWExGZXp1MUdCWHdpNEFaempMSFVsNWpSR2hMbkNZa05qdWZGZi9EQ" + + "0cKeUFWdnpMVXQwZ2F0b0dJdTV2eG9la05JVWV5YTZpRzJBaG9jSmM0SEJMT3l4TXE3Ci0tLS0tRU5EIENFUlRJRklD" + + "QVRFLS0tLS0K")) + .body("certificate.jwksUri", nullValue()); + + // Test patch REMOVE operation for certificates. + body = readResource("patch-remove-certificate.json"); + response = getResponseOfPatch(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("certificate.certificates", nullValue()); + } + + @Test(dependsOnMethods = {"testPatchIdP"}) + public void testDeleteIdP() { + + getResponseOfDelete(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId) + .then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_NO_CONTENT); + + getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId) + .then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_NOT_FOUND); + } + */ +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPSuccessTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPSuccessTest.java index ba7dfcc0609..811a8aabed9 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPSuccessTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPSuccessTest.java @@ -29,6 +29,10 @@ import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.wso2.carbon.automation.engine.context.TestUserMode; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.model.AuthenticationType; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.model.Endpoint; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.model.FederatedAuthenticatorRequest; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.util.UserDefinedAuthenticatorPayload; import java.io.IOException; import java.util.HashMap; @@ -45,7 +49,19 @@ public class IdPSuccessTest extends IdPTestBase { private String idPId; + private String customIdPId; private String idPTemplateId; + private UserDefinedAuthenticatorPayload userDefinedAuthenticatorPayload; + private String idpCreatePayload; + + private static final String FEDERATED_AUTHENTICATOR_ID_PLACEHOLDER = ""; + private static final String FEDERATED_AUTHENTICATOR_PLACEHOLDER = "\"\""; + private static final String FEDERATED_AUTHENTICATOR_ID = "Y3VzdG9tQXV0aGVudGljYXRvcg=="; + private static final String ENDPOINT_URI = "https://abc.com/authenticate"; + private static final String USERNAME = "username"; + private static final String PASSWORD = "password"; + private static final String USERNAME_VALUE = "testUser"; + private static final String PASSWORD_VALUE = "testPassword"; @Factory(dataProvider = "restAPIUserConfigProvider") public IdPSuccessTest(TestUserMode userMode) throws Exception { @@ -61,6 +77,30 @@ public IdPSuccessTest(TestUserMode userMode) throws Exception { public void init() throws IOException { super.testInit(API_VERSION, swaggerDefinition, tenant); + userDefinedAuthenticatorPayload = createUserDefinedAuthenticatorPayload(); + idpCreatePayload = readResource("add-idp-with-custom-fed-auth.json"); + + } + + private UserDefinedAuthenticatorPayload createUserDefinedAuthenticatorPayload() { + + UserDefinedAuthenticatorPayload userDefinedAuthenticatorPayload = new UserDefinedAuthenticatorPayload(); + userDefinedAuthenticatorPayload.setIsEnabled(true); + userDefinedAuthenticatorPayload.setAuthenticatorId(FEDERATED_AUTHENTICATOR_ID); + userDefinedAuthenticatorPayload.setDefinedBy(FederatedAuthenticatorRequest.DefinedByEnum.USER.toString()); + + Endpoint endpoint = new Endpoint(); + endpoint.setUri(ENDPOINT_URI); + AuthenticationType authenticationType = new AuthenticationType(); + authenticationType.setType(AuthenticationType.TypeEnum.BASIC); + Map properties = new HashMap<>(); + properties.put(USERNAME, USERNAME_VALUE); + properties.put(PASSWORD, PASSWORD_VALUE); + authenticationType.setProperties(properties); + endpoint.authentication(authenticationType); + userDefinedAuthenticatorPayload.setEndpoint(endpoint); + + return userDefinedAuthenticatorPayload; } @AfterClass(alwaysRun = true) @@ -256,6 +296,26 @@ public void testGetMetaOutboundConnector() throws IOException { .body("rulesEnabled", equalTo(false)); } + @Test + public void testAddIdPWithUserDefinedAuthenticator() throws IOException { + + String body = idpCreatePayload.replace(FEDERATED_AUTHENTICATOR_ID_PLACEHOLDER, + userDefinedAuthenticatorPayload.getAuthenticatorId()); + body = body.replace(FEDERATED_AUTHENTICATOR_PLACEHOLDER, + userDefinedAuthenticatorPayload.convertToJasonPayload()); + Response response = getResponseOfPost(IDP_API_BASE_PATH, body); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_CREATED) + .header(HttpHeaders.LOCATION, notNullValue()); + + String location = response.getHeader(HttpHeaders.LOCATION); + assertNotNull(location); + customIdPId = location.substring(location.lastIndexOf("/") + 1); + assertNotNull(customIdPId); + } + @Test(dependsOnMethods = {"testGetMetaOutboundConnector"}) public void testAddIdP() throws IOException { diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/AuthenticationType.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/AuthenticationType.java new file mode 100644 index 00000000000..67232e2a518 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/AuthenticationType.java @@ -0,0 +1,162 @@ +/* + * 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.identity.integration.test.rest.api.server.idp.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +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/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/Endpoint.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/Endpoint.java new file mode 100644 index 00000000000..66be70e6f61 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/Endpoint.java @@ -0,0 +1,114 @@ +/* + * 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.identity.integration.test.rest.api.server.idp.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.Valid; +import javax.validation.constraints.Pattern; +import java.util.Objects; + +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/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/FederatedAuthenticatorRequest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/FederatedAuthenticatorRequest.java index d281b5611fb..9c49cdfdbf2 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/FederatedAuthenticatorRequest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/model/FederatedAuthenticatorRequest.java @@ -23,6 +23,9 @@ import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.OpenIDConnectConfiguration; import javax.validation.Valid; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -107,6 +110,38 @@ public String toString() { "}"; } + @XmlType(name="DefinedByEnum") + @XmlEnum(String.class) + public enum DefinedByEnum { + + @XmlEnumValue("SYSTEM") SYSTEM(String.valueOf("SYSTEM")), @XmlEnumValue("USER") USER(String.valueOf("USER")); + + + private String value; + + DefinedByEnum(String v) { + value = v; + } + + public String value() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + public static DefinedByEnum fromValue(String value) { + for (DefinedByEnum b : DefinedByEnum.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + } + /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). @@ -125,6 +160,8 @@ public static class FederatedAuthenticator { private Boolean isEnabled = false; private Boolean isDefault = false; private List properties = null; + private DefinedByEnum definedBy; + private Endpoint endpoint; /** * @@ -234,16 +271,63 @@ public FederatedAuthenticator addProperty(Property property) { return this; } + /** + * + **/ + public FederatedAuthenticator definedBy(DefinedByEnum definedBy) { + + this.definedBy = definedBy; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("definedBy") + @Valid + public DefinedByEnum getDefinedBy() { + return definedBy; + } + public void setDefinedBy(DefinedByEnum definedBy) { + this.definedBy = definedBy; + } + + /** + **/ + public FederatedAuthenticator endpoint(Endpoint endpoint) { + + this.endpoint = endpoint; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("endpoint") + @Valid + public Endpoint getEndpoint() { + return endpoint; + } + public void setEndpoint(Endpoint endpoint) { + this.endpoint = endpoint; + } + @Override public String toString() { - return "class FederatedAuthenticator {\n" + + String classToString = "class FederatedAuthenticator {\n" + " authenticatorId: " + toIndentedString(authenticatorId) + "\n" + " name: " + toIndentedString(name) + "\n" + " isEnabled: " + toIndentedString(isEnabled) + "\n" + - " isDefault: " + toIndentedString(isDefault) + "\n" + - " properties: " + toIndentedString(properties) + "\n" + - "}"; + + " isDefault: " + toIndentedString(isDefault) + "\n"; + if (properties != null) { + classToString += " properties: " + toIndentedString(properties) + "\n"; + } + if (definedBy != null) { + classToString += " definedBy: " + toIndentedString(definedBy) + "\n"; + } + if (endpoint != null) { + classToString += " endpoint: " + toIndentedString(endpoint) + "\n"; + } + + return classToString + "}"; } } } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/util/UserDefinedAuthenticatorPayload.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/util/UserDefinedAuthenticatorPayload.java new file mode 100644 index 00000000000..79bcb71aec3 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/util/UserDefinedAuthenticatorPayload.java @@ -0,0 +1,77 @@ +/* + * 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.identity.integration.test.rest.api.server.idp.v1.util; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.wso2.identity.integration.test.rest.api.server.idp.v1.model.Endpoint; + +public class UserDefinedAuthenticatorPayload { + + @JsonProperty("isEnabled") + private Boolean isEnabled; + + @JsonProperty("authenticatorId") + private String authenticatorId; + + @JsonProperty("definedBy") + private String definedBy; + + @JsonProperty("endpoint") + private Endpoint endpoint; + + public Boolean getIsEnabled() { + return isEnabled; + } + + public void setIsEnabled(Boolean isEnabled) { + this.isEnabled = isEnabled; + } + + public String getAuthenticatorId() { + return authenticatorId; + } + + public void setAuthenticatorId(String authenticatorId) { + this.authenticatorId = authenticatorId; + } + + public String getDefinedBy() { + return definedBy; + } + + public void setDefinedBy(String definedBy) { + this.definedBy = definedBy; + } + + public Endpoint getEndpoint() { + return endpoint; + } + + public void setEndpoint(Endpoint endpoint) { + this.endpoint = endpoint; + } + + public String convertToJasonPayload() throws JsonProcessingException { + + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(this); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/add-idp-with-custom-fed-auth.json b/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/add-idp-with-custom-fed-auth.json new file mode 100644 index 00000000000..81f6fb6aaa6 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/add-idp-with-custom-fed-auth.json @@ -0,0 +1,38 @@ +{ + "name": "Custom Auth IDP", + "description": "IdP with user defined federated authenticator", + "image": "https://example.com/image", + "isPrimary": false, + "isFederationHub": false, + "homeRealmIdentifier": "localhost", + "alias": "https://localhost:9444/oauth2/token", + "claims": { + "userIdClaim": { + "uri": "http://wso2.org/claims/username" + }, + "roleClaim": { + "uri": "http://wso2.org/claims/role" + }, + "provisioningClaims": [ + { + "claim": { + "uri": "http://wso2.org/claims/username" + }, + "defaultValue": "sathya" + } + ] + }, + "federatedAuthenticators": { + "defaultAuthenticatorId": "", + "authenticators": [ + "" + ] + }, + "provisioning": { + "jit": { + "isEnabled": true, + "scheme": "PROVISION_SILENTLY", + "userstore": "PRIMARY" + } + } +}