diff --git a/modules/api-resources/api-resources-full/pom.xml b/modules/api-resources/api-resources-full/pom.xml index 34680fe7537..4b274403394 100644 --- a/modules/api-resources/api-resources-full/pom.xml +++ b/modules/api-resources/api-resources-full/pom.xml @@ -500,5 +500,13 @@ org.wso2.carbon.identity.server.api org.wso2.carbon.identity.api.server.action.management.common + + org.wso2.carbon.identity.server.api + org.wso2.carbon.identity.api.server.rule.metadata.v1 + + + org.wso2.carbon.identity.server.api + org.wso2.carbon.identity.api.server.rule.metadata.common + diff --git a/modules/api-resources/api-resources-full/src/main/webapp/WEB-INF/beans.xml b/modules/api-resources/api-resources-full/src/main/webapp/WEB-INF/beans.xml index 476a6c5b88e..3fa00cc159e 100644 --- a/modules/api-resources/api-resources-full/src/main/webapp/WEB-INF/beans.xml +++ b/modules/api-resources/api-resources-full/src/main/webapp/WEB-INF/beans.xml @@ -80,6 +80,7 @@ + @@ -147,6 +148,7 @@ + diff --git a/modules/api-resources/pom.xml b/modules/api-resources/pom.xml index c24179881dd..6a2fac4e2e9 100644 --- a/modules/api-resources/pom.xml +++ b/modules/api-resources/pom.xml @@ -515,6 +515,16 @@ org.wso2.carbon.identity.api.server.action.management.common ${identity.server.api.version} + + org.wso2.carbon.identity.server.api + org.wso2.carbon.identity.api.server.rule.metadata.v1 + ${identity.server.api.version} + + + org.wso2.carbon.identity.server.api + org.wso2.carbon.identity.api.server.rule.metadata.common + ${identity.server.api.version} + diff --git a/modules/distribution/src/assembly/bin.xml b/modules/distribution/src/assembly/bin.xml index a09594ff090..3edd2fc81f7 100644 --- a/modules/distribution/src/assembly/bin.xml +++ b/modules/distribution/src/assembly/bin.xml @@ -181,6 +181,17 @@ **/ + + + + ../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/resources/identity/rulemeta + + wso2is-${pom.version}/repository/resources/identity/rulemeta + + **/*.json + + + src/repository/resources/conf/templates wso2is-${pom.version}/repository/resources/conf/templates diff --git a/modules/integration/tests-integration/tests-backend/pom.xml b/modules/integration/tests-integration/tests-backend/pom.xml index 51350a63419..ebf130c74ac 100644 --- a/modules/integration/tests-integration/tests-backend/pom.xml +++ b/modules/integration/tests-integration/tests-backend/pom.xml @@ -458,19 +458,6 @@ run - - packaging-war-artifacts-oidc - process-test-resources - - - - - - - - run - - packaging-war-artifacts-passivests process-test-resources diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/PasswordlessSMSOTPAuthTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/PasswordlessSMSOTPAuthTestCase.java index 527dad0a3fb..85de57987ae 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/PasswordlessSMSOTPAuthTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/PasswordlessSMSOTPAuthTestCase.java @@ -39,7 +39,7 @@ import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.wso2.carbon.automation.engine.context.TestUserMode; -import org.wso2.identity.integration.test.base.MockClientCallback; +import org.wso2.identity.integration.test.base.MockApplicationServer; import org.wso2.identity.integration.test.base.MockSMSProvider; import org.wso2.identity.integration.test.oidc.OIDCAbstractIntegrationTest; import org.wso2.identity.integration.test.oidc.OIDCUtilTest; @@ -90,7 +90,7 @@ public class PasswordlessSMSOTPAuthTestCase extends OIDCAbstractIntegrationTest private String authorizationCode; private MockSMSProvider mockSMSProvider; - private MockClientCallback mockClientCallback; + private MockApplicationServer mockApplicationServer; private TestUserMode userMode; @@ -116,8 +116,8 @@ public void testInit() throws Exception { mockSMSProvider = new MockSMSProvider(); mockSMSProvider.start(); - mockClientCallback = new MockClientCallback(); - mockClientCallback.start(); + mockApplicationServer = new MockApplicationServer(); + mockApplicationServer.start(); super.init(); @@ -170,7 +170,7 @@ public void atEnd() throws Exception { scim2RestClient.closeHttpClient(); mockSMSProvider.stop(); - mockClientCallback.stop(); + mockApplicationServer.stop(); } @Test(groups = "wso2.is", description = "Test passwordless authentication with SMS OTP") @@ -189,7 +189,7 @@ private void sendAuthorizeRequest() throws Exception { List urlParameters = new ArrayList<>(); urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE)); urlParameters.add(new BasicNameValuePair("client_id", oidcApplication.getClientId())); - urlParameters.add(new BasicNameValuePair("redirect_uri", MockClientCallback.CALLBACK_URL)); + urlParameters.add(new BasicNameValuePair("redirect_uri", oidcApplication.getCallBackURL())); urlParameters.add(new BasicNameValuePair("scope", "openid")); @@ -212,7 +212,7 @@ private void performUserLogin() throws Exception { HttpResponse response = sendLoginPostForOtp(client, sessionDataKey, mockSMSProvider.getOTP()); EntityUtils.consume(response.getEntity()); - authorizationCode = mockClientCallback.getAuthorizationCode(); + authorizationCode = mockApplicationServer.getAuthorizationCodeForApp(oidcApplication.getApplicationName()); assertNotNull(authorizationCode); } @@ -241,7 +241,7 @@ private HttpResponse sendTokenRequestForCodeGrant() throws Exception { List urlParameters = new ArrayList<>(); urlParameters.add(new BasicNameValuePair("code", authorizationCode)); urlParameters.add(new BasicNameValuePair("grant_type", OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE)); - urlParameters.add(new BasicNameValuePair("redirect_uri", MockClientCallback.CALLBACK_URL)); + urlParameters.add(new BasicNameValuePair("redirect_uri", oidcApplication.getCallBackURL())); urlParameters.add(new BasicNameValuePair("client_id", oidcApplication.getClientSecret())); urlParameters.add(new BasicNameValuePair("scope", "openid")); @@ -259,9 +259,8 @@ private HttpResponse sendTokenRequestForCodeGrant() throws Exception { private OIDCApplication initOIDCApplication() { - OIDCApplication playgroundApp = new OIDCApplication(OIDCUtilTest.playgroundAppOneAppName, - OIDCUtilTest.playgroundAppOneAppContext, - MockClientCallback.CALLBACK_URL); + OIDCApplication playgroundApp = new OIDCApplication(MockApplicationServer.Constants.APP1.NAME, + MockApplicationServer.Constants.APP1.CALLBACK_URL); return playgroundApp; } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/SecondaryStoreUserLoginTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/SecondaryStoreUserLoginTestCase.java index 598c449f16a..e23be6dec76 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/SecondaryStoreUserLoginTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/auth/SecondaryStoreUserLoginTestCase.java @@ -208,7 +208,7 @@ private void checkAuthorizationCode(String sessionDataKeyConsent) throws Excepti private void createAndRegisterPlaygroundApplication() throws Exception { - playgroundApp = new OIDCApplication(PLAYGROUND_APP_NAME, PLAYGROUND_APP_CONTEXT, PLAYGROUND_APP_CALLBACK_URI); + playgroundApp = new OIDCApplication(PLAYGROUND_APP_NAME, PLAYGROUND_APP_CALLBACK_URI); playgroundApp.addRequiredClaim(OIDCUtilTest.emailClaimUri); playgroundApp.addRequiredClaim(OIDCUtilTest.firstNameClaimUri); playgroundApp.addRequiredClaim(OIDCUtilTest.lastNameClaimUri); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/MockApplicationServer.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/MockApplicationServer.java new file mode 100644 index 00000000000..ab5455d8fd8 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/MockApplicationServer.java @@ -0,0 +1,231 @@ +/* + * 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.base; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import com.github.tomakehurst.wiremock.extension.ResponseTransformerV2; +import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer; +import com.github.tomakehurst.wiremock.http.Response; +import com.github.tomakehurst.wiremock.stubbing.ServeEvent; +import org.wso2.identity.integration.common.utils.ISIntegrationTest; +import org.wso2.identity.integration.test.util.Utils; + +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; + +/** + * Mock application server to test OIDC related flows. + */ +public class MockApplicationServer { + + public static class MockClient { + private final AtomicReference authorizationCode = new AtomicReference<>(); + private final AtomicReference errorCode = new AtomicReference<>(); + + public AtomicReference getAuthorizationCode() { + return authorizationCode; + } + + public AtomicReference getErrorCode() { + return errorCode; + } + } + + public static class Constants { + public static class APP1 { + public static final String CALLBACK_URL = "https://localhost:8091/dummyApp/oauth2client"; + public static final String NAME = "playground.appone"; + public static final String CALLBACK_URL_PATH = "/dummyApp/oauth2client"; + } + + public static class APP2 { + public static final String CALLBACK_URL = "https://localhost:8091/dummyApp2/oauth2client"; + public static final String NAME = "playground.apptwo"; + public static final String CALLBACK_URL_PATH = "/dummyApp2/oauth2client"; + } + } + + private final Map apps = new HashMap<>(); + + private WireMockServer wireMockServer; + + public MockApplicationServer() { + + MockClient app1 = new MockClient(); + MockClient app2 = new MockClient(); + apps.put(Constants.APP1.NAME, app1); + apps.put(Constants.APP2.NAME, app2); + } + + public void start() { + + wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig() + .httpsPort(8091) + .httpDisabled(true) + .keystorePath(Paths.get(Utils.getResidentCarbonHome(), "repository", "resources", "security", + ISIntegrationTest.KEYSTORE_NAME).toAbsolutePath().toString()) + .keystorePassword("wso2carbon") + .keyManagerPassword("wso2carbon") + .extensions(new ResponseTemplateTransformer(null, true, null, null), + new ResponseTransformerV2() { + + @Override + public Response transform(Response response, ServeEvent serveEvent) { + + AtomicReference authorizationCode + = (AtomicReference) serveEvent.getTransformerParameters().get("code"); + authorizationCode.set(serveEvent.getRequest().getQueryParams().get("code") + .firstValue()); + return response; + } + + @Override + public boolean applyGlobally() { + return false; + } + + @Override + public String getName() { + return "authz-code-transformer"; + } + }, + new ResponseTransformerV2() { + + @Override + public Response transform(Response response, ServeEvent serveEvent) { + + AtomicReference errorCode + = (AtomicReference) serveEvent.getTransformerParameters().get("error"); + errorCode.set(serveEvent.getRequest().getQueryParams().get("error").firstValue()); + return response; + } + + @Override + public boolean applyGlobally() { + return false; + } + + @Override + public String getName() { + return "error-code-transformer"; + } + })); + + wireMockServer.start(); + + // Configure the mock client endpoints for App 1 + configureMockEndpointsForApp(Constants.APP1.CALLBACK_URL_PATH, apps.get(Constants.APP1.NAME)); + // Configure the mock client endpoints for App 2 + configureMockEndpointsForApp(Constants.APP2.CALLBACK_URL_PATH, apps.get(Constants.APP2.NAME)); + } + + public void stop() { + + if (wireMockServer != null) { + wireMockServer.stop(); + } + } + + private void configureMockEndpointsForApp(String urlPath, MockClient app) { + + try { + wireMockServer.stubFor(get(urlPathEqualTo(urlPath)) + .withQueryParam("code", matching(".*")) + .willReturn(aResponse() + .withTransformers("response-template", "authz-code-transformer") + .withTransformerParameter("code", app.getAuthorizationCode()) + .withTransformerParameter("error", app.getErrorCode()) + .withStatus(200))); + wireMockServer.stubFor(post(urlPathEqualTo(urlPath)) + .withQueryParam("code", matching(".*")) + .willReturn(aResponse() + .withTransformers("response-template", "authz-code-transformer") + .withTransformerParameter("code", app.getAuthorizationCode()) + .withTransformerParameter("error", app.getErrorCode()) + .withStatus(200))); + wireMockServer.stubFor(get(urlPathEqualTo(urlPath)) + .withQueryParam("code", matching(".*")) + .withQueryParam("session_state", matching(".*")) + .willReturn(aResponse() + .withTransformers("response-template", "authz-code-transformer") + .withTransformerParameter("code", app.getAuthorizationCode()) + .withTransformerParameter("error", app.getErrorCode()) + .withStatus(200))); + wireMockServer.stubFor(post(urlPathEqualTo(urlPath)) + .withQueryParam("code", matching(".*")) + .withQueryParam("session_state", matching(".*")) + .willReturn(aResponse() + .withTransformers("response-template", "authz-code-transformer") + .withTransformerParameter("code", app.getAuthorizationCode()) + .withTransformerParameter("error", app.getErrorCode()) + .withStatus(200))); + wireMockServer.stubFor(get(urlPathEqualTo(urlPath)) + .withQueryParam("error_description", matching(".*")) + .withQueryParam("error", matching(".*")) + .willReturn(aResponse() + .withTransformers("response-template", "error-code-transformer") + .withTransformerParameter("code", app.getAuthorizationCode()) + .withTransformerParameter("error", app.getErrorCode()) + .withStatus(200))); + wireMockServer.stubFor(get(urlEqualTo(urlPath)) + .willReturn(aResponse() + .withTransformers("response-template") + .withStatus(200))); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void verifyLogoutRedirectionForApp(String appName) { + + wireMockServer.verify(getRequestedFor(urlEqualTo(getCallbackUrlPath(appName)))); + } + + public String getAuthorizationCodeForApp(String appName) { + + return apps.get(appName).getAuthorizationCode().get(); + } + + public String getErrorCode(String appName) { + + return apps.get(appName).getErrorCode().get(); + } + + private String getCallbackUrlPath(String appName) { + switch (appName) { + case Constants.APP1.NAME: + return Constants.APP1.CALLBACK_URL_PATH; + case Constants.APP2.NAME: + return Constants.APP2.CALLBACK_URL_PATH; + default: + throw new IllegalArgumentException("Unknown app name: " + appName); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/MockClientCallback.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/MockClientCallback.java deleted file mode 100644 index 955f56ba48d..00000000000 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/MockClientCallback.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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.base; - -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.core.WireMockConfiguration; -import com.github.tomakehurst.wiremock.extension.ResponseTransformerV2; -import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer; -import com.github.tomakehurst.wiremock.http.Response; -import com.github.tomakehurst.wiremock.stubbing.ServeEvent; -import org.wso2.identity.integration.common.utils.ISIntegrationTest; -import org.wso2.identity.integration.test.util.Utils; - -import java.nio.file.Paths; -import java.util.concurrent.atomic.AtomicReference; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.matching; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; - -/** - * Mock client callback endpoint to test OIDC related flows. - */ -public class MockClientCallback { - - public static final String CALLBACK_URL = "https://localhost:8091/dummyApp/oauth2client"; - - private final AtomicReference authorizationCode = new AtomicReference<>(); - - private WireMockServer wireMockServer; - - public void start() { - - wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig() - .httpsPort(8091) - .httpDisabled(true) - .keystorePath(Paths.get(Utils.getResidentCarbonHome(), "repository", "resources", "security", - ISIntegrationTest.KEYSTORE_NAME).toAbsolutePath().toString()) - .keystorePassword("wso2carbon") - .keyManagerPassword("wso2carbon") - .extensions(new ResponseTemplateTransformer(null, true, null, null), - new ResponseTransformerV2() { - - @Override - public Response transform(Response response, ServeEvent serveEvent) { - - authorizationCode.set(serveEvent.getRequest().getQueryParams().get("code").firstValue()); - return response; - } - - @Override - public boolean applyGlobally() { - return false; - } - - @Override - public String getName() { - return "authz-code-transformer"; - } - })); - - wireMockServer.start(); - - // Configure the mock client endpoints. - configureMockEndpoints(); - } - - public void stop() { - - if (wireMockServer != null) { - wireMockServer.stop(); - } - } - - private void configureMockEndpoints() { - - try { - wireMockServer.stubFor(get(urlPathEqualTo("/dummyApp/oauth2client")) - .withQueryParam("code", matching(".*")) - .willReturn(aResponse() - .withTransformers("response-template", "authz-code-transformer") - .withStatus(200))); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public String getAuthorizationCode() { - - return authorizationCode.get(); - } -} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/TomcatInitializerTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/TomcatInitializerTestCase.java index 743c9b3b19b..2fdc751b53c 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/TomcatInitializerTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/base/TomcatInitializerTestCase.java @@ -43,8 +43,6 @@ public class TomcatInitializerTestCase extends ISIntegrationTest { "travelocity.com-registrymount", "avis.com", "PassiveSTSSampleApp", - "playground.appone", - "playground.apptwo", "playground2" }; private static final Log LOG = LogFactory.getLog(TomcatInitializerTestCase.class); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2TokenExchangeGrantTypeTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2TokenExchangeGrantTypeTestCase.java index 13921edf7ae..813b6bbb3be 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2TokenExchangeGrantTypeTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/OAuth2TokenExchangeGrantTypeTestCase.java @@ -566,8 +566,7 @@ private OAuthConsumerAppDTO getOAuthConsumerAppDTO(OIDCApplication application) private void updateServiceProviderWithOIDCConfigs(int portOffset, String applicationName, ServiceProvider serviceProvider) throws Exception { - OIDCApplication application = new OIDCApplication(applicationName, "/" + applicationName, - OAuth2Constant.CALLBACK_URL); + OIDCApplication application = new OIDCApplication(applicationName, OAuth2Constant.CALLBACK_URL); OAuthConsumerAppDTO appDTO = getOAuthConsumerAppDTO(application); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAbstractIntegrationTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAbstractIntegrationTest.java index 6742e9b8823..1f5dc59d813 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAbstractIntegrationTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAbstractIntegrationTest.java @@ -20,13 +20,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.CookieStore; import org.apache.http.client.HttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.util.EntityUtils; +import org.apache.http.message.BasicNameValuePair; import org.testng.Assert; import org.wso2.carbon.automation.engine.context.TestUserMode; import org.wso2.identity.integration.test.oauth2.OAuth2ServiceAbstractIntegrationTest; @@ -53,6 +51,8 @@ import java.util.List; import java.util.Map; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZE_ENDPOINT_URL; + /** * This class defines basic functionality needed to initiate an OIDC test. */ @@ -188,28 +188,19 @@ public void testSendAuthenticationRequest(OIDCApplication application, boolean i HttpClient client, CookieStore cookieStore) throws Exception { - List urlParameters = OIDCUtilTest.getNameValuePairs(application, - getTenantQualifiedURL(OAuth2Constant.APPROVAL_URL, tenantInfo.getDomain())); - - HttpResponse response = sendPostRequestWithParameters(client, urlParameters, String.format - (OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + OAuth2Constant.PlaygroundAppPaths - .appUserAuthorizePath)); + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE)); + urlParameters.add(new BasicNameValuePair("client_id", application.getClientId())); + urlParameters.add(new BasicNameValuePair("redirect_uri", application.getCallBackURL())); - Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); - EntityUtils.consume(response.getEntity()); + urlParameters.add(new BasicNameValuePair("scope", "openid")); - if (isFirstAuthenticationRequest) { - response = sendGetRequest(client, locationHeader.getValue()); - } else { - HttpClient httpClientWithoutAutoRedirections = HttpClientBuilder.create().disableRedirectHandling() - .setDefaultCookieStore(cookieStore).build(); - response = sendGetRequest(httpClientWithoutAutoRedirections, locationHeader.getValue()); - } + HttpResponse response = sendPostRequestWithParameters(client, urlParameters, + getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain())); Map keyPositionMap = new HashMap<>(1); if (isFirstAuthenticationRequest) { OIDCUtilTest.setSessionDataKey(response, keyPositionMap); - } else { Assert.assertFalse(Utils.requestMissingClaims(response)); } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAuthCodeGrantSSOTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAuthCodeGrantSSOTestCase.java index 730c5aed824..221ebf6e788 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAuthCodeGrantSSOTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCAuthCodeGrantSSOTestCase.java @@ -33,6 +33,7 @@ import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.cookie.RFC6265CookieSpecProvider; +import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.json.simple.JSONValue; @@ -40,6 +41,7 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import org.wso2.identity.integration.test.base.MockApplicationServer; import org.wso2.identity.integration.test.oidc.bean.OIDCApplication; import org.wso2.identity.integration.test.rest.api.user.common.model.Email; import org.wso2.identity.integration.test.rest.api.user.common.model.Name; @@ -49,7 +51,6 @@ import org.wso2.identity.integration.test.utils.OAuth2Constant; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; import java.util.ArrayList; @@ -57,6 +58,11 @@ import java.util.List; import java.util.Map; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.ACCESS_TOKEN_ENDPOINT; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZATION_HEADER; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZE_ENDPOINT_URL; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE; + /** * This test class tests OIDC SSO functionality for two replying party applications. */ @@ -76,6 +82,7 @@ public class OIDCAuthCodeGrantSSOTestCase extends OIDCAbstractIntegrationTest { protected RequestConfig requestConfig; protected HttpClient client; protected List consentParameters = new ArrayList<>(); + private MockApplicationServer mockApplicationServer; @BeforeClass(alwaysRun = true) public void testInit() throws Exception { @@ -100,6 +107,9 @@ public void testInit() throws Exception { .setDefaultCookieStore(cookieStore) .build(); + mockApplicationServer = new MockApplicationServer(); + mockApplicationServer.start(); + } @AfterClass(alwaysRun = true) @@ -108,6 +118,7 @@ public void testClear() throws Exception { deleteUser(user); deleteApplications(); clear(); + mockApplicationServer.stop(); } @Test(groups = "wso2.is", description = "Test authz endpoint before creating a valid session") @@ -122,12 +133,13 @@ public void testAuthzRequestWithoutValidSessionForIDENTITY5581() throws Exceptio .addParameter("prompt", "none") .addParameter("redirect_uri", application.getCallBackURL()).build(); HttpResponse httpResponse = sendGetRequest(client, uri.toString()); - String contentData = DataExtractUtil.getContentData(httpResponse); - Assert.assertTrue(contentData.contains("login_required")); + EntityUtils.consume(httpResponse.getEntity()); + Assert.assertTrue(mockApplicationServer.getErrorCode(application.getApplicationName()).contains("login_required")); } - @Test(groups = "wso2.is", description = "Initiate authentication request from playground.appone", dependsOnMethods = "testAuthzRequestWithoutValidSessionForIDENTITY5581") + @Test(groups = "wso2.is", description = "Initiate authentication request from playground.appone", + dependsOnMethods = "testAuthzRequestWithoutValidSessionForIDENTITY5581") public void testSendAuthenticationRequestFromRP1() throws Exception { testSendAuthenticationRequest(applications.get(OIDCUtilTest.playgroundAppOneAppName), true, client, cookieStore); @@ -164,7 +176,8 @@ public void testUserClaimsFromRP1() throws Exception { @Test(groups = "wso2.is", description = "Initiate authentication request from playground.apptwo") public void testSendAuthenticationRequestFromRP2() throws Exception { - testSendAuthenticationRequest(applications.get(OIDCUtilTest.playgroundAppTwoAppName), false, client, cookieStore); + testSendAuthenticationRequest(applications.get(OIDCUtilTest.playgroundAppTwoAppName), false, client, + cookieStore); } @Test(groups = "wso2.is", description = "Approve consent for playground.apptwo", dependsOnMethods = @@ -189,23 +202,22 @@ public void testUserClaimsFromRP2() throws Exception { } public void testSendAuthenticationRequest(OIDCApplication application, boolean isFirstAuthenticationRequest, - HttpClient client, CookieStore cookieStore) - throws Exception { - - List urlParameters = OIDCUtilTest.getNameValuePairs(application); - HttpResponse response = sendPostRequestWithParameters(client, urlParameters, String.format - (OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + OAuth2Constant.PlaygroundAppPaths - .appUserAuthorizePath)); - Assert.assertNotNull(response, "Authorization request failed for " + application.getApplicationName() + ". " - + "Authorized response is null"); + HttpClient client, CookieStore cookieStore) throws Exception { - Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE)); + urlParameters.add(new BasicNameValuePair("client_id", application.getClientId())); + urlParameters.add(new BasicNameValuePair("redirect_uri", application.getCallBackURL())); - Assert.assertNotNull(locationHeader, "Authorization request failed for " + application.getApplicationName() + - ". Authorized response header is null"); - EntityUtils.consume(response.getEntity()); + urlParameters.add(new BasicNameValuePair("scope", "openid email profile")); + HttpResponse response; if (isFirstAuthenticationRequest) { + response = sendPostRequestWithParameters(client, urlParameters, + getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain())); + Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); + EntityUtils.consume(response.getEntity()); + response = sendGetRequest(client, locationHeader.getValue()); } else { HttpClient httpClientWithoutAutoRedirections = HttpClientBuilder.create() @@ -213,11 +225,12 @@ public void testSendAuthenticationRequest(OIDCApplication application, boolean i .setDefaultRequestConfig(requestConfig) .disableRedirectHandling() .setDefaultCookieStore(cookieStore).build(); - response = sendGetRequest(httpClientWithoutAutoRedirections, locationHeader.getValue()); + response = sendPostRequestWithParameters(httpClientWithoutAutoRedirections, urlParameters, + getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain())); } - Assert.assertNotNull(response, "Authorization request failed for " + application.getApplicationName() + ". " - + "Authorized user response is null."); + Assert.assertNotNull(response, "Authorization request failed for " + application.getApplicationName() + + ". Authorized user response is null."); Map keyPositionMap = new HashMap<>(1); if (isFirstAuthenticationRequest) { @@ -238,12 +251,11 @@ public void testSendAuthenticationRequest(OIDCApplication application, boolean i String pastrCookie = Utils.getPastreCookie(response); Assert.assertNotNull(pastrCookie, "pastr cookie not found in response."); EntityUtils.consume(response.getEntity()); - Header oauthConsentLocationHeader = consentLocationHeader; - Assert.assertNotNull(oauthConsentLocationHeader, "OAuth consent url is null for " + - oauthConsentLocationHeader.getValue()); + Assert.assertNotNull(consentLocationHeader, "OAuth consent url is null for " + + consentLocationHeader.getValue()); consentParameters.addAll(Utils.getConsentRequiredClaimsFromResponse(response)); - response = sendGetRequest(client, oauthConsentLocationHeader.getValue()); + response = sendGetRequest(client, consentLocationHeader.getValue()); keyPositionMap.put("name=\"sessionDataKeyConsent\"", 1); List keyValues = DataExtractUtil.extractSessionConsentDataFromResponse @@ -272,6 +284,7 @@ private void testAuthentication(OIDCApplication application) throws Exception { EntityUtils.consume(response.getEntity()); response = sendGetRequest(client, locationHeader.getValue()); + Map keyPositionMap = new HashMap<>(1); keyPositionMap.put("name=\"sessionDataKeyConsent\"", 1); List keyValues = DataExtractUtil.extractSessionConsentDataFromResponse(response, @@ -297,16 +310,10 @@ private void testConsentApproval(OIDCApplication application) throws Exception { EntityUtils.consume(response.getEntity()); response = sendPostRequest(client, locationHeader.getValue()); - Assert.assertNotNull(response, "Authorization code response is invalid for " + application.getApplicationName - ()); - - Map keyPositionMap = new HashMap<>(1); - keyPositionMap.put("Authorization Code", 1); - List keyValues = DataExtractUtil.extractTableRowDataFromResponse(response, - keyPositionMap); - Assert.assertNotNull(keyValues, "Authorization code not received for " + application.getApplicationName()); + Assert.assertNotNull(response, "Authorization code response is invalid for " + + application.getApplicationName()); - authorizationCode = keyValues.get(0).getValue(); + authorizationCode = mockApplicationServer.getAuthorizationCodeForApp(application.getApplicationName()); Assert.assertNotNull(authorizationCode, "Authorization code not received for " + application .getApplicationName()); EntityUtils.consume(response.getEntity()); @@ -314,35 +321,33 @@ private void testConsentApproval(OIDCApplication application) throws Exception { private void testGetAccessToken(OIDCApplication application) throws Exception { - HttpResponse response = sendGetAccessTokenPost(client, application); - Assert.assertNotNull(response, "Access token response is invalid for " + application.getApplicationName()); - EntityUtils.consume(response.getEntity()); - - response = sendPostRequest(client, String.format(OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + - OAuth2Constant.PlaygroundAppPaths.appAuthorizePath)); - - Map keyPositionMap = new HashMap<>(1); - keyPositionMap.put("name=\"accessToken\"", 1); - List keyValues = DataExtractUtil.extractInputValueFromResponse(response, - keyPositionMap); - Assert.assertNotNull(keyValues, "Access token not received for " + application.getApplicationName()); - - accessToken = keyValues.get(0).getValue(); - Assert.assertNotNull(accessToken, "Access token not received for " + application.getApplicationName()); - EntityUtils.consume(response.getEntity()); - - response = sendPostRequest(client, String.format(OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + - OAuth2Constant.PlaygroundAppPaths.appAuthorizePath)); - - keyPositionMap = new HashMap<>(1); - keyPositionMap.put("id=\"loggedUser\"", 1); - keyValues = DataExtractUtil.extractLabelValueFromResponse(response, keyPositionMap); - Assert.assertNotNull(keyValues, "No user logged in for " + application.getApplicationName()); + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("code", authorizationCode)); + urlParameters.add(new BasicNameValuePair("grant_type", OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE)); + urlParameters.add(new BasicNameValuePair("redirect_uri", application.getCallBackURL())); + urlParameters.add(new BasicNameValuePair("client_id", application.getClientSecret())); + + urlParameters.add(new BasicNameValuePair("scope", "openid")); + + List
headers = new ArrayList<>(); + headers.add(new BasicHeader(AUTHORIZATION_HEADER, + OAuth2Constant.BASIC_HEADER + " " + getBase64EncodedString(application.getClientId(), + application.getClientSecret()))); + headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded")); + headers.add(new BasicHeader("User-Agent", OAuth2Constant.USER_AGENT)); + + HttpResponse response = sendPostRequest(client, headers, urlParameters, + getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + String responseString = EntityUtils.toString(response.getEntity()); + Map responseMap = (Map) JSONValue.parse(responseString); + accessToken = (String) responseMap.get("access_token"); + + String idToken = (String) responseMap.get("id_token"); + String[] tokenParts = idToken.split("\\."); + String payload = new String(java.util.Base64.getUrlDecoder().decode(tokenParts[1])); + Map parsedIdToken = (Map) JSONValue.parse(payload); + Assert.assertNotNull(parsedIdToken.get("sub"), "No user logged in for " + application.getApplicationName()); - String loggedUser = keyValues.get(0).getValue(); - Assert.assertNotNull(loggedUser, "Logged user is null for " + application.getApplicationName()); - Assert.assertNotEquals(loggedUser, "null", "Logged user is null for " + application.getApplicationName()); - Assert.assertNotEquals(loggedUser, "", "Logged user is null for " + application.getApplicationName()); EntityUtils.consume(response.getEntity()); } @@ -376,14 +381,13 @@ protected void initUser() throws Exception { protected void initApplications() throws Exception { OIDCApplication playgroundApp = new OIDCApplication(OIDCUtilTest.playgroundAppOneAppName, - OIDCUtilTest.playgroundAppOneAppContext, OIDCUtilTest.playgroundAppOneAppCallBackUri); playgroundApp.addRequiredClaim(OIDCUtilTest.emailClaimUri); playgroundApp.addRequiredClaim(OIDCUtilTest.firstNameClaimUri); playgroundApp.addRequiredClaim(OIDCUtilTest.lastNameClaimUri); applications.put(OIDCUtilTest.playgroundAppOneAppName, playgroundApp); - playgroundApp = new OIDCApplication(OIDCUtilTest.playgroundAppTwoAppName, OIDCUtilTest.playgroundAppTwoAppContext, + playgroundApp = new OIDCApplication(OIDCUtilTest.playgroundAppTwoAppName, OIDCUtilTest.playgroundAppTwoAppCallBackUri); playgroundApp.addRequiredClaim(OIDCUtilTest.emailClaimUri); playgroundApp.addRequiredClaim(OIDCUtilTest.firstNameClaimUri); @@ -404,17 +408,4 @@ protected void deleteApplications() throws Exception { deleteApplication(entry.getValue()); } } - - protected HttpResponse sendGetAccessTokenPost(HttpClient client, OIDCApplication application) throws IOException { - - List urlParameters = new ArrayList<>(); - urlParameters.add(new BasicNameValuePair("callbackurl", application.getCallBackURL())); - urlParameters.add(new BasicNameValuePair("accessEndpoint", OAuth2Constant.ACCESS_TOKEN_ENDPOINT)); - urlParameters.add(new BasicNameValuePair("consumerSecret", application.getClientSecret())); - HttpResponse response = sendPostRequestWithParameters(client, urlParameters, String.format - (OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + OAuth2Constant.PlaygroundAppPaths - .accessTokenRequestPath)); - - return response; - } } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCRPInitiatedLogoutTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCRPInitiatedLogoutTestCase.java index f9729d7711c..db6a2b48545 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCRPInitiatedLogoutTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCRPInitiatedLogoutTestCase.java @@ -32,6 +32,7 @@ import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import org.wso2.identity.integration.test.base.MockApplicationServer; import org.wso2.identity.integration.test.oidc.bean.OIDCApplication; import org.wso2.identity.integration.test.rest.api.user.common.model.Email; import org.wso2.identity.integration.test.rest.api.user.common.model.Name; @@ -45,6 +46,8 @@ import java.util.List; import java.util.Map; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZE_ENDPOINT_URL; + /** * This test class tests the OIDC RP-Initiated logout flows */ @@ -62,6 +65,7 @@ public class OIDCRPInitiatedLogoutTestCase extends OIDCAbstractIntegrationTest { protected List consentParameters = new ArrayList<>(); OIDCApplication playgroundAppOne; OIDCApplication playgroundAppTwo; + private MockApplicationServer mockApplicationServer; @BeforeClass(alwaysRun = true) public void testInit() throws Exception { @@ -88,6 +92,9 @@ public void testInit() throws Exception { .setDefaultCookieSpecRegistry(cookieSpecRegistry) .setDefaultRequestConfig(requestConfig) .build(); + + mockApplicationServer = new MockApplicationServer(); + mockApplicationServer.start(); } @AfterClass(alwaysRun = true) @@ -97,6 +104,7 @@ public void testClear() throws Exception { deleteApplication(playgroundAppOne); deleteApplication(playgroundAppTwo); clear(); + mockApplicationServer.stop(); } @AfterMethod @@ -145,12 +153,14 @@ public void testOIDCLogoutPrecedence() throws Exception { private void testInitiateOIDCRequest(OIDCApplication application, HttpClient client) throws Exception { - List urlParameters = OIDCUtilTest.getNameValuePairs(application); - HttpResponse response = sendPostRequestWithParameters(client, urlParameters, String.format - (OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + - OAuth2Constant.PlaygroundAppPaths.appUserAuthorizePath)); - Assert.assertNotNull(response, "Authorization request failed for " + application.getApplicationName() + - ". Authorized response is null."); + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE)); + urlParameters.add(new BasicNameValuePair("client_id", application.getClientId())); + urlParameters.add(new BasicNameValuePair("redirect_uri", application.getCallBackURL())); + urlParameters.add(new BasicNameValuePair("scope", "openid email profile")); + + HttpResponse response = sendPostRequestWithParameters(client, urlParameters, + getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain())); Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); @@ -196,13 +206,8 @@ private void testOIDCLogin(OIDCApplication application, boolean checkConsent) th sessionDataKeyConsent = keyValues.get(0).getValue(); Assert.assertNotNull(sessionDataKeyConsent, "sessionDataKeyConsent is null."); } else { - keyPositionMap.put("Authorization Code", 1); - List keyValues = DataExtractUtil.extractTableRowDataFromResponse(response, - keyPositionMap); - Assert.assertNotNull(keyValues, "Authorization code not received for " + - application.getApplicationName()); - - authorizationCode = new AuthorizationCode(keyValues.get(0).getValue()); + authorizationCode = new AuthorizationCode( + mockApplicationServer.getAuthorizationCodeForApp(application.getApplicationName())); Assert.assertNotNull(authorizationCode, "Authorization code not received for " + application .getApplicationName()); } @@ -221,17 +226,8 @@ private void testOIDCConsentApproval(OIDCApplication application) throws Excepti EntityUtils.consume(response.getEntity()); response = sendPostRequest(client, locationHeader.getValue()); - Assert.assertNotNull(response, "Authorization code response is invalid for " + - application.getApplicationName()); - - Map keyPositionMap = new HashMap<>(1); - keyPositionMap.put("Authorization Code", 1); - List keyValues = DataExtractUtil.extractTableRowDataFromResponse(response, - keyPositionMap); - Assert.assertNotNull(keyValues, "Authorization code not received for " + - application.getApplicationName()); - - authorizationCode = new AuthorizationCode(keyValues.get(0).getValue()); + authorizationCode = new AuthorizationCode( + mockApplicationServer.getAuthorizationCodeForApp(application.getApplicationName())); Assert.assertNotNull(authorizationCode, "Authorization code not received for " + application .getApplicationName()); EntityUtils.consume(response.getEntity()); @@ -296,10 +292,8 @@ private void testOIDCLogout(boolean checkSuccess, OIDCApplication application, B Assert.assertTrue(redirectUrl.contains(application.getCallBackURL()), "Not redirected to the" + "post logout redirect url"); response = sendGetRequest(client, redirectUrl); - Assert.assertNotNull(response, "OIDC Logout failed."); - String result = DataExtractUtil.getContentData(response); - Assert.assertTrue(result.contains("WSO2 OAuth2 Playground"), "OIDC logout failed."); EntityUtils.consume(response.getEntity()); + mockApplicationServer.verifyLogoutRedirectionForApp(application.getApplicationName()); } else { Assert.assertTrue(redirectUrl.contains("oauth2_error.do")); } @@ -320,7 +314,6 @@ protected void initUser() { protected OIDCApplication initApplicationOne() { playgroundAppOne = new OIDCApplication(OIDCUtilTest.playgroundAppOneAppName, - OIDCUtilTest.playgroundAppOneAppContext, OIDCUtilTest.playgroundAppOneAppCallBackUri); playgroundAppOne.addRequiredClaim(OIDCUtilTest.emailClaimUri); playgroundAppOne.addRequiredClaim(OIDCUtilTest.firstNameClaimUri); @@ -330,7 +323,6 @@ protected OIDCApplication initApplicationOne() { protected OIDCApplication initApplicationTwo() { playgroundAppTwo = new OIDCApplication(OIDCUtilTest.playgroundAppTwoAppName, - OIDCUtilTest.playgroundAppTwoAppContext, OIDCUtilTest.playgroundAppTwoAppCallBackUri); playgroundAppOne.addRequiredClaim(OIDCUtilTest.emailClaimUri); playgroundAppOne.addRequiredClaim(OIDCUtilTest.firstNameClaimUri); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSPWiseSkipLoginConsentTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSPWiseSkipLoginConsentTestCase.java index 20061ed6240..ac33d2b6ef7 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSPWiseSkipLoginConsentTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSPWiseSkipLoginConsentTestCase.java @@ -30,6 +30,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.wso2.carbon.automation.engine.context.TestUserMode; +import org.wso2.identity.integration.test.base.MockApplicationServer; import org.wso2.identity.integration.test.oidc.bean.OIDCApplication; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.AdvancedApplicationConfiguration; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.ApplicationPatchModel; @@ -46,6 +47,7 @@ public class OIDCSPWiseSkipLoginConsentTestCase extends OIDCAbstractIntegrationT private CookieStore cookieStore = new BasicCookieStore(); protected String sessionDataKey; protected String sessionDataKeyConsent; + private MockApplicationServer mockApplicationServer; @BeforeClass(alwaysRun = true) public void testInit() throws Exception { @@ -57,6 +59,9 @@ public void testInit() throws Exception { createApplications(); configureSPToSkipConsent(); client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build(); + + mockApplicationServer = new MockApplicationServer(); + mockApplicationServer.start(); } @AfterClass(alwaysRun = true) @@ -64,6 +69,7 @@ public void clearObjects() throws Exception { deleteObjects(); clear(); + mockApplicationServer.stop(); } private void deleteObjects() throws Exception { @@ -83,16 +89,16 @@ private void configureSPToSkipConsent() throws Exception { @Test(groups = "wso2.is", description = "Test authz endpoint before creating a valid session") public void testCreateUserSession() throws Exception { - testSendAuthenticationRequest(OIDCUtilTest.applications.get(OIDCUtilTest.playgroundAppOneAppName), true, client, - cookieStore); + testSendAuthenticationRequest(OIDCUtilTest.applications.get(OIDCUtilTest.playgroundAppOneAppName), true, + client, cookieStore); testAuthentication(); } @Test(groups = "wso2.is", description = "Initiate authentication request from playground.apptwo") - public void testIntiateLoginRequestForAlreadyLoggedUser() throws Exception { + public void testInitiateLoginRequestForAlreadyLoggedUser() throws Exception { - testSendAuthenticationRequest(OIDCUtilTest.applications.get(OIDCUtilTest.playgroundAppTwoAppName), false, client - , cookieStore); + testSendAuthenticationRequest(OIDCUtilTest.applications.get(OIDCUtilTest.playgroundAppTwoAppName), false, + client, cookieStore); } private void testAuthentication() throws Exception { diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSSOConsentTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSSOConsentTestCase.java index e71147375b9..138cd18c3c6 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSSOConsentTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCSSOConsentTestCase.java @@ -31,9 +31,11 @@ import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.cookie.RFC6265CookieSpecProvider; +import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.json.JSONObject; +import org.json.simple.JSONValue; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -41,6 +43,7 @@ import org.wso2.carbon.automation.engine.context.beans.Tenant; import org.wso2.carbon.automation.engine.context.beans.User; import org.apache.commons.lang.StringUtils; +import org.wso2.identity.integration.test.base.MockApplicationServer; import org.wso2.identity.integration.test.oidc.bean.OIDCApplication; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.ApplicationPatchModel; import org.wso2.identity.integration.test.rest.api.server.application.management.v1.model.Claim; @@ -55,8 +58,11 @@ import org.wso2.identity.integration.test.utils.OAuth2Constant; import static org.apache.commons.lang.StringUtils.isBlank; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.ACCESS_TOKEN_ENDPOINT; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZATION_HEADER; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZE_ENDPOINT_URL; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -81,6 +87,7 @@ public class OIDCSSOConsentTestCase extends OIDCAbstractIntegrationTest { protected List consentParameters = new ArrayList<>(); OIDCApplication playgroundApp; private String claimsToGetConsent; + private MockApplicationServer mockApplicationServer; @BeforeClass(alwaysRun = true) public void testInit() throws Exception { @@ -105,6 +112,9 @@ public void testInit() throws Exception { .setDefaultCookieSpecRegistry(cookieSpecRegistry) .setDefaultRequestConfig(requestConfig) .build(); + + mockApplicationServer = new MockApplicationServer(); + mockApplicationServer.start(); } @AfterClass(alwaysRun = true) @@ -113,6 +123,7 @@ public void testClear() throws Exception { deleteUser(user); deleteApplication(playgroundApp); clear(); + mockApplicationServer.stop(); } @Test(groups = "wso2.is", description = "Test consent management after updating " + @@ -140,17 +151,16 @@ public void testConsentWithAppClaimConfigUpdate() throws Exception { public void testSendAuthenticationRequest(OIDCApplication application, HttpClient client) throws Exception { - List urlParameters = OIDCUtilTest.getNameValuePairs(application); - HttpResponse response = sendPostRequestWithParameters(client, urlParameters, String.format - (OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + - OAuth2Constant.PlaygroundAppPaths.appUserAuthorizePath)); - Assert.assertNotNull(response, "Authorization request failed for " + application.getApplicationName() + - ". Authorized response is null."); + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE)); + urlParameters.add(new BasicNameValuePair("client_id", application.getClientId())); + urlParameters.add(new BasicNameValuePair("redirect_uri", application.getCallBackURL())); + + urlParameters.add(new BasicNameValuePair("scope", "openid email profile")); + HttpResponse response = sendPostRequestWithParameters(client, urlParameters, + getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain())); Header locationHeader = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); - - Assert.assertNotNull(locationHeader, "Authorization request failed for " + - application.getApplicationName() + ". Authorized response header is null."); EntityUtils.consume(response.getEntity()); response = sendGetRequest(client, locationHeader.getValue()); @@ -222,53 +232,41 @@ private void testConsentApproval(OIDCApplication application) throws Exception { EntityUtils.consume(response.getEntity()); response = sendPostRequest(client, locationHeader.getValue()); - Assert.assertNotNull(response, "Authorization code response is invalid for " + - application.getApplicationName()); - - Map keyPositionMap = new HashMap<>(1); - keyPositionMap.put("Authorization Code", 1); - List keyValues = DataExtractUtil.extractTableRowDataFromResponse(response, - keyPositionMap); - Assert.assertNotNull(keyValues, "Authorization code not received for " + - application.getApplicationName()); + EntityUtils.consume(response.getEntity()); - authorizationCode = keyValues.get(0).getValue(); + authorizationCode = mockApplicationServer.getAuthorizationCodeForApp(application.getApplicationName()); Assert.assertNotNull(authorizationCode, "Authorization code not received for " + application .getApplicationName()); - EntityUtils.consume(response.getEntity()); } private void testGetAccessToken(OIDCApplication application) throws Exception { - HttpResponse response = sendGetAccessTokenPost(client, application); - Assert.assertNotNull(response, "Access token response is invalid for " + - application.getApplicationName()); - EntityUtils.consume(response.getEntity()); - - response = sendPostRequest(client, String.format(OIDCUtilTest.targetApplicationUrl, - application.getApplicationContext() + OAuth2Constant.PlaygroundAppPaths.appAuthorizePath)); - - Map keyPositionMap = new HashMap<>(1); - keyPositionMap.put("name=\"accessToken\"", 1); - List keyValues = DataExtractUtil.extractInputValueFromResponse(response, - keyPositionMap); - Assert.assertNotNull(keyValues, "Access token not received for " + application.getApplicationName()); - - accessToken = keyValues.get(0).getValue(); - Assert.assertNotNull(accessToken, "Access token not received for " + application.getApplicationName()); - EntityUtils.consume(response.getEntity()); - - response = sendPostRequest(client, String.format(OIDCUtilTest.targetApplicationUrl, - application.getApplicationContext() + OAuth2Constant.PlaygroundAppPaths.appAuthorizePath)); - - keyPositionMap = new HashMap<>(1); - keyPositionMap.put("id=\"loggedUser\"", 1); - keyValues = DataExtractUtil.extractLabelValueFromResponse(response, keyPositionMap); - Assert.assertNotNull(keyValues, "No user logged in for " + application.getApplicationName()); - - String loggedUser = keyValues.get(0).getValue(); - Assert.assertNotNull(loggedUser, "Logged user is null for " + application.getApplicationName()); - EntityUtils.consume(response.getEntity()); + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("code", authorizationCode)); + urlParameters.add(new BasicNameValuePair("grant_type", OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE)); + urlParameters.add(new BasicNameValuePair("redirect_uri", application.getCallBackURL())); + urlParameters.add(new BasicNameValuePair("client_id", application.getClientSecret())); + + urlParameters.add(new BasicNameValuePair("scope", "openid")); + + List
headers = new ArrayList<>(); + headers.add(new BasicHeader(AUTHORIZATION_HEADER, + OAuth2Constant.BASIC_HEADER + " " + getBase64EncodedString(application.getClientId(), + application.getClientSecret()))); + headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded")); + headers.add(new BasicHeader("User-Agent", OAuth2Constant.USER_AGENT)); + + HttpResponse response = sendPostRequest(client, headers, urlParameters, + getTenantQualifiedURL(ACCESS_TOKEN_ENDPOINT, tenantInfo.getDomain())); + String responseString = EntityUtils.toString(response.getEntity()); + Map responseMap = (Map) JSONValue.parse(responseString); + accessToken = (String) responseMap.get("access_token"); + + String idToken = (String) responseMap.get("id_token"); + String[] tokenParts = idToken.split("\\."); + String payload = new String(java.util.Base64.getUrlDecoder().decode(tokenParts[1])); + Map parsedIdToken = (Map) JSONValue.parse(payload); + Assert.assertNotNull(parsedIdToken.get("sub"), "No user logged in for " + application.getApplicationName()); } protected void initUser() throws Exception { @@ -283,7 +281,6 @@ protected void initUser() throws Exception { protected OIDCApplication initApplication() { playgroundApp = new OIDCApplication(OIDCUtilTest.playgroundAppOneAppName, - OIDCUtilTest.playgroundAppOneAppContext, OIDCUtilTest.playgroundAppOneAppCallBackUri); playgroundApp.addRequiredClaim(OIDCUtilTest.emailClaimUri); playgroundApp.addRequiredClaim(OIDCUtilTest.firstNameClaimUri); @@ -306,19 +303,6 @@ private void updateApplication(OIDCApplication playgroundApp) throws Exception { updateApplication(playgroundApp.getApplicationId(), new ApplicationPatchModel().claimConfiguration(claimConfig)); } - protected HttpResponse sendGetAccessTokenPost(HttpClient client, OIDCApplication application) throws IOException { - - List urlParameters = new ArrayList<>(); - urlParameters.add(new BasicNameValuePair("callbackurl", application.getCallBackURL())); - urlParameters.add(new BasicNameValuePair("accessEndpoint", OAuth2Constant.ACCESS_TOKEN_ENDPOINT)); - urlParameters.add(new BasicNameValuePair("consumerSecret", application.getClientSecret())); - HttpResponse response = sendPostRequestWithParameters(client, urlParameters, String.format - (OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + - OAuth2Constant.PlaygroundAppPaths.accessTokenRequestPath)); - - return response; - } - private void performOIDCLogout() { try { diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCUtilTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCUtilTest.java index 9fd38e90710..8a5f866d25b 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCUtilTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/OIDCUtilTest.java @@ -22,6 +22,7 @@ import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.message.BasicNameValuePair; +import org.wso2.identity.integration.test.base.MockApplicationServer; import org.wso2.identity.integration.test.oidc.bean.OIDCApplication; import org.wso2.identity.integration.test.rest.api.user.common.model.Email; import org.wso2.identity.integration.test.rest.api.user.common.model.Name; @@ -54,17 +55,11 @@ public class OIDCUtilTest { public static final String profile = "default"; protected static String sessionDataKey; - public static final String playgroundAppOneAppName = "playground.appone"; - public static final String playgroundAppOneAppCallBackUri = "http://localhost:" + TOMCAT_PORT + "/playground" + "" + - ".appone/oauth2client"; - public static final String playgroundAppOneAppContext = "/playground.appone"; + public static final String playgroundAppOneAppName = MockApplicationServer.Constants.APP1.NAME; + public static final String playgroundAppOneAppCallBackUri = MockApplicationServer.Constants.APP1.CALLBACK_URL; - public static final String playgroundAppTwoAppName = "playground.apptwo"; - public static final String playgroundAppTwoAppCallBackUri = "http://localhost:" + TOMCAT_PORT + "/playground" + "" + - ".apptwo/oauth2client"; - public static final String playgroundAppTwoAppContext = "/playground.apptwo"; - - public static final String targetApplicationUrl = "http://localhost:" + TOMCAT_PORT + "%s"; + public static final String playgroundAppTwoAppName = MockApplicationServer.Constants.APP2.NAME; + public static final String playgroundAppTwoAppCallBackUri = MockApplicationServer.Constants.APP2.CALLBACK_URL; public static final String emailClaimUri = "http://wso2.org/claims/emailaddress"; public static final String firstNameClaimUri = "http://wso2.org/claims/givenname"; @@ -87,14 +82,14 @@ public static void initUser() { */ public static void initApplications() { - OIDCApplication playgroundApp = new OIDCApplication(playgroundAppOneAppName, playgroundAppOneAppContext, + OIDCApplication playgroundApp = new OIDCApplication(playgroundAppOneAppName, playgroundAppOneAppCallBackUri); playgroundApp.addRequiredClaim(emailClaimUri); playgroundApp.addRequiredClaim(firstNameClaimUri); playgroundApp.addRequiredClaim(lastNameClaimUri); applications.put(playgroundAppOneAppName, playgroundApp); - playgroundApp = new OIDCApplication(playgroundAppTwoAppName, playgroundAppTwoAppContext, + playgroundApp = new OIDCApplication(playgroundAppTwoAppName, playgroundAppTwoAppCallBackUri); playgroundApp.addRequiredClaim(emailClaimUri); playgroundApp.addRequiredClaim(firstNameClaimUri); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/bean/OIDCApplication.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/bean/OIDCApplication.java index c42ecbc0e9e..a71263f1109 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/bean/OIDCApplication.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oidc/bean/OIDCApplication.java @@ -27,7 +27,6 @@ public class OIDCApplication { private String applicationName; private String clientId; private String clientSecret; - private String applicationContext; private String callBackURL; private String subjectClaimURI; private List requiredClaims = null; @@ -36,9 +35,8 @@ public OIDCApplication() { } - public OIDCApplication(String applicationName, String applicationContext, String callBackURL) { + public OIDCApplication(String applicationName, String callBackURL) { this.applicationName = applicationName; - this.applicationContext = applicationContext; this.callBackURL = callBackURL; } @@ -74,14 +72,6 @@ public void setClientSecret(String clientSecret) { this.clientSecret = clientSecret; } - public String getApplicationContext() { - return applicationContext; - } - - public void setApplicationContext(String applicationContext) { - this.applicationContext = applicationContext; - } - public String getCallBackURL() { return callBackURL; } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/recovery/PasswordRecoveryTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/recovery/PasswordRecoveryTestCase.java index cc6f9981325..c699c6006bd 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/recovery/PasswordRecoveryTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/recovery/PasswordRecoveryTestCase.java @@ -43,6 +43,7 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import org.wso2.identity.integration.test.base.MockApplicationServer; import org.wso2.identity.integration.test.oidc.OIDCAbstractIntegrationTest; import org.wso2.identity.integration.test.oidc.OIDCUtilTest; import org.wso2.identity.integration.test.oidc.bean.OIDCApplication; @@ -60,6 +61,8 @@ import java.util.ArrayList; import java.util.List; +import static org.wso2.identity.integration.test.utils.OAuth2Constant.AUTHORIZE_ENDPOINT_URL; + /** * Test password recovery functionality. */ @@ -72,6 +75,7 @@ public class PasswordRecoveryTestCase extends OIDCAbstractIntegrationTest { private CloseableHttpClient client; private OIDCApplication oidcApplication; private UserObject userObject; + private MockApplicationServer mockApplicationServer; public static final String USERNAME = "recoverytestuser"; public static final String PASSWORD = "Oidcsessiontestuser@123"; @@ -103,6 +107,9 @@ public void testInit() throws Exception { userObject = initUser(); createUser(userObject); + + mockApplicationServer = new MockApplicationServer(); + mockApplicationServer.start(); } @AfterClass(alwaysRun = true) @@ -114,6 +121,7 @@ public void testClear() throws Exception { identityGovernanceRestClient.closeHttpClient(); client.close(); Utils.getMailServer().purgeEmailFromAllMailboxes(); + mockApplicationServer.stop(); } @Test @@ -129,12 +137,13 @@ public void testPasswordRecovery() throws Exception { private String retrievePasswordResetURL(OIDCApplication application, HttpClient client) throws Exception { - List urlParameters = OIDCUtilTest.getNameValuePairs(application, - getTenantQualifiedURL(OAuth2Constant.APPROVAL_URL, tenantInfo.getDomain())); - - HttpResponse response = sendPostRequestWithParameters(client, urlParameters, String.format - (OIDCUtilTest.targetApplicationUrl, application.getApplicationContext() + OAuth2Constant.PlaygroundAppPaths - .appUserAuthorizePath)); + List urlParameters = new ArrayList<>(); + urlParameters.add(new BasicNameValuePair("response_type", OAuth2Constant.OAUTH2_GRANT_TYPE_CODE)); + urlParameters.add(new BasicNameValuePair("client_id", application.getClientId())); + urlParameters.add(new BasicNameValuePair("redirect_uri", application.getCallBackURL())); + urlParameters.add(new BasicNameValuePair("scope", "openid email profile")); + HttpResponse response = sendPostRequestWithParameters(client, urlParameters, + getTenantQualifiedURL(AUTHORIZE_ENDPOINT_URL, tenantInfo.getDomain())); Header authorizeRequestURL = response.getFirstHeader(OAuth2Constant.HTTP_RESPONSE_HEADER_LOCATION); EntityUtils.consume(response.getEntity()); @@ -192,7 +201,6 @@ private void updatePasswordRecoveryFeatureStatus(boolean enable) throws IOExcept private OIDCApplication initApplication() { OIDCApplication playgroundApp = new OIDCApplication(OIDCUtilTest.playgroundAppOneAppName, - OIDCUtilTest.playgroundAppOneAppContext, OIDCUtilTest.playgroundAppOneAppCallBackUri); playgroundApp.addRequiredClaim(OIDCUtilTest.emailClaimUri); playgroundApp.addRequiredClaim(OIDCUtilTest.firstNameClaimUri); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPFailureTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPFailureTest.java index 95968d5f352..6bd2ad93707 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPFailureTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/idp/v1/IdPFailureTest.java @@ -63,6 +63,7 @@ public class IdPFailureTest extends IdPTestBase { private static final String ENDPOINT_URI = "https://abc.com/authenticate"; private String idPId; private String idpCreatePayload; + private static final String OIDC_IDP_ID = "T3BlbklEQ29ubmVjdEF1dGhlbnRpY2F0b3I"; @Factory(dataProvider = "restAPIUserConfigProvider") public IdPFailureTest(TestUserMode userMode) throws Exception { @@ -562,4 +563,58 @@ private void deleteCreatedIdP(String idPId) { .body("description", equalTo("Unable to find a resource matching the provided identity " + "provider identifier " + idPId + ".")); } + + @Test + public void testUpdateIdPWithDuplicateOIDCScopes() throws IOException { + + String body = readResource("add-idp-oidc-standard-based.json"); + 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); + String oidcIdPId = location.substring(location.lastIndexOf("/") + 1); + assertNotNull(oidcIdPId); + + // update the OIDC IDP with duplicated scopes + String updateBody = readResource("update-idp-oidc-standard-based-duplicated-scopes.json"); + Response updateResponse = getResponseOfPut(IDP_API_BASE_PATH + PATH_SEPARATOR + oidcIdPId + + PATH_SEPARATOR + IDP_FEDERATED_AUTHENTICATORS_PATH + PATH_SEPARATOR + OIDC_IDP_ID, updateBody); + updateResponse.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_BAD_REQUEST) + .body("message", equalTo("Duplicate OIDC Scopes.")) + .body("description", equalTo("Cannot set scopes in both Scopes and Additional Query Parameters. " + + "Recommend to use Scopes field.")); + + deleteCreatedIdP(oidcIdPId); + } + + /** + * Deletes an Identity Provider by its ID and verifies the deletion. + * + * @param idPId ID of the Identity Provider to be deleted. + */ + private void deleteCreatedIdP(String idPId) { + + Response response = getResponseOfDelete(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_NO_CONTENT); + + Response responseOfGet = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + idPId); + responseOfGet.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_NOT_FOUND) + .body("message", equalTo("Resource not found.")) + .body("description", equalTo("Unable to find a resource matching the provided identity " + + "provider identifier " + idPId + ".")); + } } 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..69ca753532a 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 @@ -16,6 +16,7 @@ package org.wso2.identity.integration.test.rest.api.server.idp.v1; +import com.fasterxml.jackson.core.JsonProcessingException; import io.restassured.RestAssured; import io.restassured.response.Response; import org.apache.commons.lang.StringUtils; @@ -29,11 +30,19 @@ 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.Base64; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import javax.xml.xpath.XPathExpressionException; + import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; @@ -44,8 +53,25 @@ */ public class IdPSuccessTest extends IdPTestBase { + private static final String FEDERATED_AUTHENTICATOR_ID_PLACEHOLDER = ""; + private static final String FEDERATED_AUTHENTICATOR_PLACEHOLDER = "\"\""; + private static final String IDP_NAME_PLACEHOLDER = ""; + private static final String FEDERATED_AUTHENTICATOR_ID = "Y3VzdG9tQXV0aGVudGljYXRvcg"; + private static final String CUSTOM_IDP_NAME = "Custom Auth IDP"; + private static final String ENDPOINT_URI = "https://abc.com/authenticate"; + private static final String UPDATED_ENDPOINT_URI = "https://xyz.com/authenticate"; + private static final String USERNAME = "username"; + private static final String PASSWORD = "password"; + private static final String ACCESS_TOKEN = "accessToken"; + private static final String USERNAME_VALUE = "testUser"; + private static final String ACCESS_TOKEN_VALUE = "testBearerToken"; + private static final String PASSWORD_VALUE = "testPassword"; + private static final String IDP_NAME = "Google"; private String idPId; + private String customIdPId; private String idPTemplateId; + private UserDefinedAuthenticatorPayload userDefinedAuthenticatorPayload; + private String idpCreatePayload; @Factory(dataProvider = "restAPIUserConfigProvider") public IdPSuccessTest(TestUserMode userMode) throws Exception { @@ -61,6 +87,50 @@ public IdPSuccessTest(TestUserMode userMode) throws Exception { public void init() throws IOException { super.testInit(API_VERSION, swaggerDefinition, tenant); + userDefinedAuthenticatorPayload = createUserDefinedAuthenticatorPayloadWithBasic(ENDPOINT_URI); + idpCreatePayload = readResource("add-idp-with-custom-fed-auth.json"); + } + + private UserDefinedAuthenticatorPayload createUserDefinedAuthenticatorPayloadWithBasic(String endpointUri) { + + UserDefinedAuthenticatorPayload userDefinedAuthenticatorPayload = new UserDefinedAuthenticatorPayload(); + userDefinedAuthenticatorPayload.setIsEnabled(true); + userDefinedAuthenticatorPayload.setAuthenticatorId(FEDERATED_AUTHENTICATOR_ID); + userDefinedAuthenticatorPayload.setDefinedBy(FederatedAuthenticatorRequest.DefinedByEnum.USER.toString()); + + Endpoint endpoint = new Endpoint(); + endpoint.setUri(endpointUri); + 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; + } + + private UserDefinedAuthenticatorPayload createUserDefinedAuthenticatorPayloadWithBearer(String endpointUri) { + + UserDefinedAuthenticatorPayload userDefinedAuthenticatorPayload = new UserDefinedAuthenticatorPayload(); + userDefinedAuthenticatorPayload.setIsEnabled(true); + userDefinedAuthenticatorPayload.setAuthenticatorId(FEDERATED_AUTHENTICATOR_ID); + userDefinedAuthenticatorPayload.setDefinedBy(FederatedAuthenticatorRequest.DefinedByEnum.USER.toString()); + + Endpoint endpoint = new Endpoint(); + endpoint.setUri(endpointUri); + AuthenticationType authenticationType = new AuthenticationType(); + authenticationType.setType(AuthenticationType.TypeEnum.BEARER); + Map properties = new HashMap<>(); + authenticationType.setType(AuthenticationType.TypeEnum.BEARER); + properties.put(ACCESS_TOKEN, ACCESS_TOKEN_VALUE); + authenticationType.setProperties(properties); + endpoint.authentication(authenticationType); + userDefinedAuthenticatorPayload.setEndpoint(endpoint); + + return userDefinedAuthenticatorPayload; } @AfterClass(alwaysRun = true) @@ -256,6 +326,88 @@ 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()); + body = body.replace(IDP_NAME_PLACEHOLDER, CUSTOM_IDP_NAME); + 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 = "testAddIdPWithUserDefinedAuthenticator") + public void testGetUserDefinedAuthenticatorsOfIdP() throws XPathExpressionException { + + Response response = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + customIdPId + + PATH_SEPARATOR + IDP_FEDERATED_AUTHENTICATORS_PATH); + + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("defaultAuthenticatorId", equalTo(FEDERATED_AUTHENTICATOR_ID)) + .body("authenticators.find { it.authenticatorId == '" + FEDERATED_AUTHENTICATOR_ID + "' }.name", + equalTo(new String(Base64.getDecoder().decode(FEDERATED_AUTHENTICATOR_ID)))) + .body("authenticators.find { it.authenticatorId == '" + FEDERATED_AUTHENTICATOR_ID + "' }.isEnabled", + equalTo(true)) + .body("authenticators.find { it.authenticatorId == '" + FEDERATED_AUTHENTICATOR_ID + "' }.self", + equalTo(getTenantedRelativePath("/api/server/v1/identity-providers/" + + customIdPId + "/federated-authenticators/" + FEDERATED_AUTHENTICATOR_ID, + context.getContextTenant().getDomain()))); + } + + @Test(dependsOnMethods = "testGetUserDefinedAuthenticatorsOfIdP") + public void testUpdateUserDefinedAuthenticatorOfIdP() throws JsonProcessingException { + + Response response = getResponseOfPut(IDP_API_BASE_PATH + PATH_SEPARATOR + customIdPId + + PATH_SEPARATOR + IDP_FEDERATED_AUTHENTICATORS_PATH + PATH_SEPARATOR + FEDERATED_AUTHENTICATOR_ID, + createUserDefinedAuthenticatorPayloadWithBearer(UPDATED_ENDPOINT_URI) + .convertToJasonPayload()); + + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("authenticatorId", equalTo(FEDERATED_AUTHENTICATOR_ID)) + .body("name", equalTo(new String(Base64.getDecoder().decode(FEDERATED_AUTHENTICATOR_ID)))) + .body("definedBy", equalTo("USER")) + .body("endpoint.uri", equalTo(UPDATED_ENDPOINT_URI)) + .body("endpoint.authentication.type", equalTo(AuthenticationType.TypeEnum.BEARER.value())); + } + + @Test(dependsOnMethods = {"testGetIdPs", "testUpdateUserDefinedAuthenticatorOfIdP"}) + public void testDeleteIdPWithUserDefinedAuthenticator() { + + Response response = getResponseOfDelete(IDP_API_BASE_PATH + PATH_SEPARATOR + customIdPId); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_NO_CONTENT); + + Response responseOfGet = getResponseOfGet(IDP_API_BASE_PATH + PATH_SEPARATOR + customIdPId); + responseOfGet.then() + .log().ifValidationFails() + .assertThat() + .assertThat() + .statusCode(HttpStatus.SC_NOT_FOUND) + .body("message", equalTo("Resource not found.")) + .body("description", equalTo("Unable to find a resource matching the provided identity " + + "provider identifier " + customIdPId + ".")); + + } + @Test(dependsOnMethods = {"testGetMetaOutboundConnector"}) public void testAddIdP() throws IOException { @@ -286,6 +438,8 @@ public void testGetIdP() throws IOException { .body("description", equalTo("IDP for Google Federation")) .body("isEnabled", equalTo(true)) .body("isPrimary", equalTo(false)) + .body("federatedAuthenticators.authenticators.find { it.authenticatorId == '" + + SAMPLE_FEDERATED_AUTHENTICATOR_ID + "' }.definedBy", equalTo("SYSTEM")) .body("image", equalTo("google-logo-url")) .body("isFederationHub", equalTo(false)) .body("homeRealmIdentifier", equalTo("localhost")) @@ -296,6 +450,7 @@ public void testGetIdP() throws IOException { public void testGetIdPs() throws Exception { String baseIdentifier = "identityProviders.find{ it.id == '" + idPId + "' }."; + String baseIdentifierUserDef = "identityProviders.find{ it.id == '" + customIdPId + "' }."; Response response = getResponseOfGet(IDP_API_BASE_PATH); response.then() .log().ifValidationFails() @@ -306,6 +461,27 @@ public void testGetIdPs() throws Exception { .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(baseIdentifierUserDef + "name", equalTo(CUSTOM_IDP_NAME)) + .body(baseIdentifierUserDef + "isEnabled", equalTo(true)) + .body(baseIdentifierUserDef + "self", equalTo(getTenantedRelativePath( + "/api/server/v1/identity-providers/" + customIdPId, + context.getContextTenant().getDomain()))); + } + + @Test(dependsOnMethods = "testGetIdP") + public void testSearchAllIdPs() throws XPathExpressionException { + + Response response = getResponseOfGetWithQueryParams(IDP_API_BASE_PATH, Collections.singletonMap("filter", + "name sw " + IDP_NAME)); + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("identityProviders.find { it.id == '" + idPId + "' }.name", equalTo(IDP_NAME)) + .body("identityProviders.find { it.id == '" + idPId + "' }.isEnabled", equalTo(true)) + .body("identityProviders.find { it.id == '" + idPId + "' }.self", equalTo(getTenantedRelativePath( "/api/server/v1/identity-providers/" + idPId, context.getContextTenant().getDomain()))); } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementFailureTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementFailureTest.java index 6922e738930..203f0b7967a 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementFailureTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementFailureTest.java @@ -540,32 +540,6 @@ public void testGetPaginatedOrganizationsDiscoveryWithInvalidLimitAndOffset(Stri validateErrorResponse(response, HttpStatus.SC_BAD_REQUEST, ERROR_CODE_BAD_REQUEST); } - /* - * TODO: After the issue https://github.com/wso2/product-is/issues/21025 is fixed, - * remove the method testGetPaginatedOrganizationsDiscoveryWithInvalidOffsetAndLimitZero - * along with its data provider organizationDiscoveryInvalidOffsetAtLimitAndLimitZeroDataProvider. - */ - @DataProvider(name = "organizationDiscoveryInvalidOffsetAtLimitAndLimitZeroDataProvider") - public Object[][] organizationDiscoveryInvalidOffsetAtLimitAndLimitZeroDataProvider() { - - return new Object[][]{ - {"20", "0"}, - {"25", "0"} - }; - } - - @Test(dependsOnMethods = "testGetPaginatedOrganizationsDiscoveryWithInvalidLimitAndOffset", - dataProvider = "organizationDiscoveryInvalidOffsetAtLimitAndLimitZeroDataProvider") - public void testGetPaginatedOrganizationsDiscoveryWithInvalidOffsetAndLimitZero(String offset, - String limit) { - - String url = ORGANIZATION_MANAGEMENT_API_BASE_PATH + ORGANIZATION_DISCOVERY_API_PATH + QUESTION_MARK + - OFFSET_QUERY_PARAM + EQUAL + offset + AMPERSAND + LIMIT_QUERY_PARAM + EQUAL + limit; - - Response response = getResponseOfGetWithOAuth2(url, m2mToken); - validateErrorResponse(response, HttpStatus.SC_INTERNAL_SERVER_ERROR, ERROR_CODE_SERVER_ERROR); - } - @Test(dependsOnMethods = "testGetPaginatedOrganizationsDiscoveryWithInvalidLimitAndOffset") public void testGetPaginatedMetaAttributesWithInvalidLimit() { diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementSuccessTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementSuccessTest.java index 92bea4666d9..2c9ccd88d3e 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementSuccessTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/organization/management/v1/OrganizationManagementSuccessTest.java @@ -798,6 +798,32 @@ public void testGetPaginatedOrganizations(int limit) { validateOrganizationsOnPage(previousPageResponse, 1, NUM_OF_ORGANIZATIONS_FOR_PAGINATION_TESTS, limit); } + @DataProvider(name = "organizationDiscoveryInvalidOffsetAtLimitAndLimitZeroDataProvider") + public Object[][] organizationDiscoveryInvalidOffsetAtLimitAndLimitZeroDataProvider() { + + return new Object[][]{ + {"20", "0"}, + {"25", "0"} + }; + } + + @Test(groups = "organizationPaginationTests", + dependsOnMethods = "createOrganizationsForPaginationTests", + dataProvider = "organizationDiscoveryInvalidOffsetAtLimitAndLimitZeroDataProvider") + public void testGetPaginatedOrganizationsDiscoveryWithInvalidOffsetAndLimitZero(String offset, + String limit) { + + String url = ORGANIZATION_MANAGEMENT_API_BASE_PATH + ORGANIZATION_DISCOVERY_API_PATH + QUESTION_MARK + + OFFSET_QUERY_PARAM + EQUAL + offset + AMPERSAND + LIMIT_QUERY_PARAM + EQUAL + limit; + + Response response = getResponseOfGetWithOAuth2(url, m2mToken); + validateHttpStatusCode(response, HttpStatus.SC_OK); + List> returnedOrganizations = response.jsonPath().getList(ORGANIZATIONS_PATH_PARAM); + Assert.assertNull(returnedOrganizations); + int totalResults = response.jsonPath().getInt("totalResults"); + Assert.assertEquals(totalResults, 0, "Total results should be 0 when the limit is 0."); + } + @DataProvider(name = "organizationPaginationNumericEdgeCasesOfLimitDataProvider") public Object[][] organizationPaginationNumericEdgeCasesOfLimitDataProvider() { @@ -806,7 +832,8 @@ public Object[][] organizationPaginationNumericEdgeCasesOfLimitDataProvider() { }; } - @Test(groups = "organizationPaginationTests", dependsOnMethods = "createOrganizationsForPaginationTests", + @Test(groups = "organizationPaginationTests", + dependsOnMethods = "testGetPaginatedOrganizationsDiscoveryWithInvalidOffsetAndLimitZero", dataProvider = "organizationPaginationNumericEdgeCasesOfLimitDataProvider") public void testGetPaginatedOrganizationsForNumericEdgeCasesOfLimit(int limit) { diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataFailureTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataFailureTest.java new file mode 100644 index 00000000000..13219d2fa82 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataFailureTest.java @@ -0,0 +1,85 @@ +/* + * 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.rules.metadata.v1; + +import io.restassured.RestAssured; +import io.restassured.response.Response; +import org.apache.http.HttpStatus; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; +import org.wso2.carbon.automation.engine.context.TestUserMode; + +import static org.hamcrest.CoreMatchers.equalTo; + +public class RulesMetadataFailureTest extends RulesMetadataTestBase { + + @DataProvider(name = "testExecutionContextProvider") + public static Object[][] getTestExecutionContext() { + + return new Object[][]{ + {TestUserMode.SUPER_TENANT_ADMIN}, + {TestUserMode.TENANT_ADMIN} + }; + } + + @Factory(dataProvider = "testExecutionContextProvider") + public RulesMetadataFailureTest(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 Exception { + + super.initTestClass(tenant); + } + + @AfterClass(alwaysRun = true) + public void conclude() { + + super.conclude(); + } + + @BeforeMethod(alwaysRun = true) + public void testInit() { + + RestAssured.basePath = basePath; + } + + @Test + public void testGetRuleMetadataForNotImplementedFlow() throws Exception { + + Response responseOfGet = getResponseOfGet(getAPIRequestForFlow("preLogin")); + responseOfGet.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_BAD_REQUEST) + .body("code", equalTo("RULEMETA-60001")) + .body("message", equalTo("Invalid flow.")) + .body("description", equalTo("Provided flow type is invalid or not implemented.")); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataSuccessTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataSuccessTest.java new file mode 100644 index 00000000000..88633f57f71 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataSuccessTest.java @@ -0,0 +1,127 @@ +/* + * 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.rules.metadata.v1; + +import io.restassured.RestAssured; +import io.restassured.response.Response; +import org.apache.http.HttpStatus; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; +import org.wso2.carbon.automation.engine.context.TestUserMode; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.Matchers.hasItems; + +public class RulesMetadataSuccessTest extends RulesMetadataTestBase { + + @DataProvider(name = "testExecutionContextProvider") + public static Object[][] getTestExecutionContext() { + + return new Object[][]{ + {TestUserMode.SUPER_TENANT_ADMIN}, + {TestUserMode.TENANT_ADMIN} + }; + } + + @Factory(dataProvider = "testExecutionContextProvider") + public RulesMetadataSuccessTest(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 Exception { + + super.initTestClass(tenant); + } + + @AfterClass(alwaysRun = true) + public void conclude() { + + super.conclude(); + } + + @BeforeMethod(alwaysRun = true) + public void testInit() { + + RestAssured.basePath = basePath; + } + + @DataProvider(name = "flowProvider") + public static Object[][] getFlows() { + + return new Object[][]{ + {"preIssueAccessToken"}, + }; + } + + @Test(dataProvider = "flowProvider") + public void testGetRuleMetadata(String flow) throws Exception { + + Response responseOfGet = getResponseOfGet(getAPIRequestForValidFlow(flow)); + validateResponse(flow, responseOfGet); + } + + private static void validateResponse(String flow, Response response) { + + if (flow.equals("preIssueAccessToken")) { + validateResponseForPreIssueAccessTokenFlow(response); + } else { + throw new IllegalArgumentException("Invalid flow: " + flow); + } + } + + private static void validateResponseForPreIssueAccessTokenFlow(Response response) { + + response.then() + .log().ifValidationFails() + .assertThat() + .statusCode(HttpStatus.SC_OK) + .body("[0].field.name", equalTo("application")) + .body("[0].field.displayName", equalTo("application")) + .body("[0].operators.name", hasItems("equals", "notEquals")) + .body("[0].operators.displayName", hasItems("equals", "not equals")) + .body("[0].value.inputType", equalTo("options")) + .body("[0].value.valueType", equalTo("reference")) + .body("[0].value.valueReferenceAttribute", equalTo("id")) + .body("[0].value.valueDisplayAttribute", equalTo("name")) + .body("[0].value.links.href", + hasItems("/applications?offset=0&limit=10", "/applications?filter=&limit=10")) + .body("[0].value.links.method", hasItems("GET")) + .body("[0].value.links.rel", hasItems("values", "filter")) + .body("[1].field.name", equalTo("grantType")) + .body("[1].field.displayName", equalTo("grant type")) + .body("[1].operators.name", hasItems("equals", "notEquals")) + .body("[1].operators.displayName", hasItems("equals", "not equals")) + .body("[1].value.inputType", equalTo("options")) + .body("[1].value.valueType", equalTo("string")) + .body("[1].value.values.name", + hasItems("authorization_code", "password", "refresh_token", "client_credentials")) + .body("[1].value.values.displayName", + hasItems("authorization code", "password", "refresh token", "client credentials")); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataTestBase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataTestBase.java new file mode 100644 index 00000000000..6dad1077fd1 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/rest/api/server/rules/metadata/v1/RulesMetadataTestBase.java @@ -0,0 +1,70 @@ +/* + * 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.rules.metadata.v1; + +import org.testng.Assert; +import org.wso2.identity.integration.test.rest.api.server.common.RESTAPIServerTestBase; + +import java.io.IOException; + +public class RulesMetadataTestBase extends RESTAPIServerTestBase { + + private static final String API_DEFINITION_NAME = "rule-metadata.yaml"; + private static final String API_VERSION = "v1"; + + private static String swaggerDefinition; + + static { + String API_PACKAGE_NAME = "org.wso2.carbon.identity.api.server.rule.metadata.v1"; + try { + swaggerDefinition = getAPISwaggerDefinition(API_PACKAGE_NAME, API_DEFINITION_NAME); + } catch (IOException e) { + Assert.fail(String.format("Unable to read the swagger definition %s from %s", API_DEFINITION_NAME, + API_PACKAGE_NAME), e); + } + } + + protected void initTestClass(String tenantDomain) throws IOException { + + super.testInit(API_VERSION, swaggerDefinition, tenantDomain); + } + + protected String getAPIRequestForValidFlow(String flow) { + + validateFlow(flow); + return getAPIEndpoint() + "?flow=" + flow; + } + + protected String getAPIRequestForFlow(String flow) { + + return getAPIEndpoint() + "?flow=" + flow; + } + + protected String getAPIEndpoint() { + + return "/rules/metadata"; + } + + private void validateFlow(String flow) { + + if (!"preIssueAccessToken".equals(flow)) { + throw new IllegalArgumentException("Invalid flow: " + flow); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/add-idp-oidc-standard-based.json b/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/add-idp-oidc-standard-based.json new file mode 100644 index 00000000000..1d5831d2577 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/add-idp-oidc-standard-based.json @@ -0,0 +1,61 @@ +{ + "name": "OIDC IdP", + "alias": "", + "description": "Authenticate users with Enterprise OIDC connections.", + "image": "assets/images/logos/enterprise.svg", + "isPrimary": false, + "roles": { + "mappings": [], + "outboundProvisioningRoles": [] + }, + "certificate": { + "jwksUri": "https://test.com/jwks", + "certificates": [ + "" + ] + }, + "claims": { + "userIdClaim": { + "uri": "" + }, + "provisioningClaims": [], + "roleClaim": { + "uri": "" + } + }, + "federatedAuthenticators": { + "defaultAuthenticatorId": "T3BlbklEQ29ubmVjdEF1dGhlbnRpY2F0b3I", + "authenticators": [ + { + "isEnabled": true, + "authenticatorId": "T3BlbklEQ29ubmVjdEF1dGhlbnRpY2F0b3I", + "properties": [ + { + "key": "ClientId", + "value": "abcd1234wxyz5678ijklmnopqrst9012" + }, + { + "key": "ClientSecret", + "value": "mnop3456qrst1234uvwx5678abcd9012" + }, + { + "key": "OAuth2AuthzEPUrl", + "value": "https://test.com/authz" + }, + { + "key": "OAuth2TokenEPUrl", + "value": "https://test.com/token" + }, + { + "key": "callbackUrl", + "value": "https://test.com/commonauth" + } + ] + } + ] + }, + "homeRealmIdentifier": "", + "isFederationHub": false, + "idpIssuerName": "", + "templateId": "enterprise-oidc-idp" +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/update-idp-oidc-standard-based-duplicated-scopes.json b/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/update-idp-oidc-standard-based-duplicated-scopes.json new file mode 100644 index 00000000000..701256b2539 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/rest/api/server/idp/v1/update-idp-oidc-standard-based-duplicated-scopes.json @@ -0,0 +1,15 @@ +{ + "authenticatorId": "T3BlbklEQ29ubmVjdEF1dGhlbnRpY2F0b3I", + "isEnabled": true, + "isDefault": true, + "properties": [ + { + "key": "commonAuthQueryParams", + "value": "scope=openid country profile" + }, + { + "key": "Scopes", + "value": "openid country profile" + } + ] +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml index 4e236d65865..630b5310073 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml @@ -240,6 +240,8 @@ + + diff --git a/modules/p2-profile-gen/pom.xml b/modules/p2-profile-gen/pom.xml index 544ad995699..caa6a56ac84 100644 --- a/modules/p2-profile-gen/pom.xml +++ b/modules/p2-profile-gen/pom.xml @@ -362,6 +362,11 @@ org.wso2.carbon.identity.framework:org.wso2.carbon.identity.certificate.management.server.feature:${carbon.identity.framework.version} + + + org.wso2.carbon.identity.framework:org.wso2.carbon.identity.rule.management.server.feature:${carbon.identity.framework.version} + + org.wso2.carbon.identity.tool.validator.sso.saml2:org.wso2.carbon.identity.tools.saml.validator.feature:${identity.tool.samlsso.validator.version} @@ -856,6 +861,10 @@ org.wso2.carbon.identity.certificate.management.server.feature.group ${carbon.identity.framework.version} + + org.wso2.carbon.identity.rule.management.server.feature.group + ${carbon.identity.framework.version} + org.wso2.carbon.identity.unique.claim.mgt.server.feature.group diff --git a/pom.xml b/pom.xml index 18d51eae101..8382a93ae88 100755 --- a/pom.xml +++ b/pom.xml @@ -2344,7 +2344,7 @@ - 7.7.15 + 7.7.19 [5.14.67, 8.0.0) @@ -2358,17 +2358,17 @@ 1.11.20 - 5.9.7 + 5.9.8 5.5.0 5.5.2 1.9.14 - 7.0.192 + 7.0.193 5.11.46 5.10.2 - 5.11.12 + 5.11.13 5.7.7 3.4.102 @@ -2386,7 +2386,7 @@ 1.9.13 - 1.9.25 + 1.9.26 @@ -2437,13 +2437,13 @@ 1.1.29 4.1.30 1.0.24 - 1.0.10 + 1.0.11 1.1.2 3.1.24 - 1.0.21 - 1.0.7 + 1.0.19 + 1.0.8 - 1.4.56 + 1.4.58 1.1.19 1.1.42 1.1.27 @@ -2456,7 +2456,7 @@ 2.0.17 - 1.3.2 + 1.3.6 1.3.45 5.5.9 @@ -2466,8 +2466,8 @@ 1.2.67 - 2.35.16 - 2.13.22 + 2.35.18 + 2.13.24 2.8.4 1.6.378 @@ -2612,7 +2612,7 @@ my-scm-server - 1.0.10 + 1.0.11 2.0.1 2.0.1