From ac97cce721572886721ce628772587fc4a7cb9b0 Mon Sep 17 00:00:00 2001 From: Prarthona Paul Date: Tue, 21 May 2024 14:51:39 -0400 Subject: [PATCH] [WFLY-19198] Move the OIDC scope related tests back to the elytron-oidc-client testsuite: add tests to wildfly testsuite --- .../oidc/client/KeycloakConfiguration.java | 33 +- .../elytron/oidc/client/OidcBaseTest.java | 83 +++++ .../OidcWithDeploymentConfigTest.java | 102 +++++- .../OidcWithSubsystemConfigTest.java | 98 +++++- .../subsystem/SimpleServletWithScope.java | 8 +- .../deployment/OidcWithInvalidScope.json | 0 .../deployment/OidcWithMultipleScopes.json | 0 .../deployment/OidcWithOpenIDScope.json | 0 .../deployment/OidcWithSingleScope.json | 0 testsuite/integration/manualmode/pom.xml | 24 -- .../elytron/oidc/KeycloakConfiguration.java | 180 ----------- .../elytron/oidc/KeycloakContainer.java | 63 ---- .../manual/elytron/oidc/OidcBaseTest.java | 302 ------------------ .../OidcWithDeploymentConfigTest.java | 191 ----------- .../OidcWithSubsystemConfigTest.java | 188 ----------- .../src/test/resources/arquillian.xml | 13 - .../manual/elytron/oidc/deployment/web.xml | 14 - 17 files changed, 314 insertions(+), 985 deletions(-) rename testsuite/integration/{manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc => elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client}/subsystem/SimpleServletWithScope.java (95%) rename testsuite/integration/{manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc => elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client}/deployment/OidcWithInvalidScope.json (100%) rename testsuite/integration/{manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc => elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client}/deployment/OidcWithMultipleScopes.json (100%) rename testsuite/integration/{manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc => elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client}/deployment/OidcWithOpenIDScope.json (100%) rename testsuite/integration/{manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc => elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client}/deployment/OidcWithSingleScope.json (100%) delete mode 100644 testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakConfiguration.java delete mode 100644 testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakContainer.java delete mode 100644 testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/OidcBaseTest.java delete mode 100644 testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithDeploymentConfigTest.java delete mode 100644 testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/subsystem/OidcWithSubsystemConfigTest.java delete mode 100644 testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/web.xml diff --git a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/KeycloakConfiguration.java b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/KeycloakConfiguration.java index 20973b71b15d..c1ac5e829f6d 100644 --- a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/KeycloakConfiguration.java +++ b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/KeycloakConfiguration.java @@ -5,6 +5,8 @@ package org.wildfly.test.integration.elytron.oidc.client; +import static org.wildfly.test.integration.elytron.oidc.client.OidcBaseTest.MULTIPLE_SCOPE_APP; +import static org.wildfly.test.integration.elytron.oidc.client.OidcBaseTest.SINGLE_SCOPE_APP; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -30,7 +32,7 @@ */ public class KeycloakConfiguration { - private static final String USER_ROLE = "user"; + public static final String USER_ROLE = "user"; public static final String JBOSS_ADMIN_ROLE = "JBossAdmin"; public static final String ALICE = "alice"; public static final String ALICE_PASSWORD = "alice123+"; @@ -53,6 +55,9 @@ public class KeycloakConfiguration { public static final String TENANT2_REALM = "tenant2"; public static final String TENANT1_ENDPOINT = "/tenant1"; public static final String TENANT2_ENDPOINT = "/tenant2"; + public static final String ALICE_FIRST_NAME = "Alice"; + public static final String ALICE_LAST_NAME = "Smith"; + public static final boolean ALICE_EMAIL_VERIFIED = true; public enum ClientAppType { OIDC_CLIENT, @@ -180,7 +185,7 @@ private static RealmRepresentation createRealm(String name, String clientSecret, realm.getUsers().add(createUser(CHARLOTTE, CHARLOTTE_PASSWORD, Arrays.asList(USER_ROLE, JBOSS_ADMIN_ROLE))); realm.getUsers().add(createUser(DAN, DAN_PASSWORD, Arrays.asList(USER_ROLE, JBOSS_ADMIN_ROLE))); } else { - realm.getUsers().add(createUser(ALICE, ALICE_PASSWORD, Arrays.asList(USER_ROLE, JBOSS_ADMIN_ROLE))); + realm.getUsers().add(createUser(ALICE, ALICE_PASSWORD, Arrays.asList(USER_ROLE, JBOSS_ADMIN_ROLE), ALICE_FIRST_NAME, ALICE_LAST_NAME, ALICE_EMAIL_VERIFIED)); realm.getUsers().add(createUser(BOB, BOB_PASSWORD, Arrays.asList(USER_ROLE))); realm.getUsers().add(createUser(CHARLIE, CHARLIE_PASSWORD, Arrays.asList(USER_ROLE, JBOSS_ADMIN_ROLE))); } @@ -205,6 +210,20 @@ private static ClientRepresentation createWebAppClient(String clientId, String c client.setRedirectUris(Arrays.asList("http://" + clientHostName + ":" + clientPort + "/" + clientApp + "/*")); } client.setEnabled(true); + + if (clientId.equals(MULTIPLE_SCOPE_APP) || clientId.equals(SINGLE_SCOPE_APP)) { + client.setOptionalClientScopes(new ArrayList<>()); + client.setDefaultClientScopes(new ArrayList<>()); + client.getDefaultClientScopes().add("web-origins"); + client.getDefaultClientScopes().add("acr"); + client.getOptionalClientScopes().add("address"); + client.getOptionalClientScopes().add("email"); + client.getOptionalClientScopes().add("profile"); + client.getOptionalClientScopes().add("phone"); + client.getDefaultClientScopes().add("roles"); + client.getOptionalClientScopes().add("offline_access"); + client.getOptionalClientScopes().add("microprofile-jwt"); + } client.setDirectAccessGrantsEnabled(directAccessGrantEnabled); if (allowedOrigin != null) { client.setWebOrigins(Collections.singletonList(allowedOrigin)); @@ -219,12 +238,16 @@ private static ClientRepresentation createBearerOnlyClient(String clientId) { client.setEnabled(true); return client; } - private static UserRepresentation createUser(String username, String password, List realmRoles) { + return createUser(username, password, realmRoles, username, username, false); + } + + private static UserRepresentation createUser(String username, String password, List realmRoles, String firstName, String lastName, boolean emailVerified) { UserRepresentation user = new UserRepresentation(); user.setUsername(username); - user.setFirstName(username); - user.setLastName(username); + user.setFirstName(firstName); + user.setLastName(lastName); + user.setEmailVerified(emailVerified); user.setEnabled(true); user.setCredentials(new ArrayList<>()); user.setRealmRoles(realmRoles); diff --git a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/OidcBaseTest.java b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/OidcBaseTest.java index d7744dfc855e..b794dc86d45f 100644 --- a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/OidcBaseTest.java +++ b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/OidcBaseTest.java @@ -5,10 +5,13 @@ package org.wildfly.test.integration.elytron.oidc.client; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SYSTEM_PROPERTY; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; +import static org.wildfly.security.http.oidc.Oidc.OIDC_SCOPE; import static org.wildfly.test.integration.elytron.oidc.client.KeycloakConfiguration.ALLOWED_ORIGIN; import java.io.IOException; @@ -39,11 +42,16 @@ import org.jboss.arquillian.container.test.api.OperateOnDeployment; import org.jboss.as.arquillian.api.ServerSetupTask; import org.jboss.as.arquillian.container.ManagementClient; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.operations.common.Util; import org.jboss.as.test.http.util.TestHttpClientUtils; +import org.jboss.as.test.integration.management.ManagementOperations; import org.jboss.as.test.integration.security.common.servlets.SimpleSecuredServlet; import org.jboss.as.test.integration.security.common.servlets.SimpleServlet; import org.jboss.as.test.shared.TestSuiteEnvironment; import org.jboss.as.test.shared.util.AssumeTestGroupUtil; +import org.jboss.as.version.Stability; +import org.jboss.dmr.ModelNode; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -52,6 +60,7 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.wildfly.common.iteration.CodePointIterator; import org.wildfly.security.jose.util.JsonSerialization; +import org.wildfly.test.integration.elytron.oidc.client.subsystem.SimpleServletWithScope; import io.restassured.RestAssured; @@ -88,6 +97,16 @@ public abstract class OidcBaseTest { static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method"; static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; public static final String CORS_CLIENT = "CorsClient"; + public static final String OPENID_SCOPE_APP = "OpenIDScopeApp"; + public static final String INVALID_SCOPE_APP = "InvalidScopeApp"; + public static final String SINGLE_SCOPE_APP = "SingleScopeApp"; + public static final String MULTIPLE_SCOPE_APP = "MultipleScopeApp"; + + private final Stability desiredStability; + + public OidcBaseTest(Stability desiredStability) { + this.desiredStability = desiredStability; + } private enum BearerAuthType { BEARER, @@ -320,6 +339,46 @@ public void testCorsRequestWithoutEnableCors() throws Exception { SimpleServlet.RESPONSE_BODY, null, CORS_CLIENT, CLIENT_SECRET, ALLOWED_ORIGIN, false); } + /** + * Tests that use different scope values to request access to claims values. + */ + + @Test + @OperateOnDeployment(OPENID_SCOPE_APP) + public void testOpenIDScope() throws Exception { + String expectedScope = OIDC_SCOPE; + loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, true, + new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), + "/" + OPENID_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, false); + } + + @Test + @OperateOnDeployment(SINGLE_SCOPE_APP) + public void testSingleScope() throws Exception { + String expectedScope = OIDC_SCOPE + "+profile"; + loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, true, + new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), + "/" + SINGLE_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, false); + } + + @Test + @OperateOnDeployment(MULTIPLE_SCOPE_APP) + public void testMultipleScope() throws Exception { + String expectedScope = OIDC_SCOPE + "+phone+profile+microprofile-jwt+email"; + loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, true, + new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), + "/" + MULTIPLE_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, false); + } + + @Test + @OperateOnDeployment(INVALID_SCOPE_APP) + public void testInvalidScope() throws Exception { + String expectedScope = OIDC_SCOPE + "+INVALID_SCOPE"; + loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, false, + new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), + "/" + INVALID_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, true); + } + public static void loginToApp(String appName, String username, String password, int expectedStatusCode, String expectedText) throws Exception { loginToApp(username, password, expectedStatusCode, expectedText, true, new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), @@ -336,6 +395,10 @@ public static void loginToApp(String appName, String username, String password, } public static void loginToApp(String username, String password, int expectedStatusCode, String expectedText, boolean loginToKeycloak, URI requestUri) throws Exception { + loginToApp(username, password, expectedStatusCode, expectedText, loginToKeycloak, requestUri, null, false); + } + + public static void loginToApp(String username, String password, int expectedStatusCode, String expectedText, boolean loginToKeycloak, URI requestUri, String expectedScope, boolean checkInvalidScope) throws Exception { CookieStore store = new BasicCookieStore(); HttpClient httpClient = TestHttpClientUtils.promiscuousCookieHttpClientBuilder() .setDefaultCookieStore(store) @@ -355,7 +418,22 @@ public static void loginToApp(String username, String password, int expectedStat if (expectedText != null) { String responseString = new BasicResponseHandler().handleResponse(afterLoginClickResponse); assertTrue("Unexpected result " + responseString, responseString.contains(expectedText)); + if (expectedScope != null) { + assertTrue(context.toString().contains("scope=" + expectedScope)); + if (expectedScope.contains("profile")) { + assertTrue(responseString.contains("profile: " + KeycloakConfiguration.ALICE_FIRST_NAME + " " + KeycloakConfiguration.ALICE_LAST_NAME)); + } + if (expectedScope.contains("email")) { + assertTrue(responseString.contains("email: " + KeycloakConfiguration.ALICE_EMAIL_VERIFIED)); + } + if (expectedScope.contains("microprofile-jwt")) { + assertTrue(responseString.contains("microprofile-jwt: [" + KeycloakConfiguration.JBOSS_ADMIN_ROLE + ", " + KeycloakConfiguration.USER_ROLE + "]")); + } + } } + } else if (checkInvalidScope) { + assertTrue(context.toString().contains("error_description=Invalid+scopes")); + assertTrue("Expected code == BAD REQUEST but got " + statusCode + " for request=" + requestUri, statusCode == HttpURLConnection.HTTP_BAD_REQUEST); } else { assertTrue("Expected code == FORBIDDEN but got " + statusCode + " for request=" + requestUri, statusCode == HttpURLConnection.HTTP_FORBIDDEN); } @@ -653,4 +731,9 @@ public enum Type { HIDDEN, SUBMIT } } + protected static void addSystemProperty(ManagementClient client, Class clazz) throws Exception { + ModelNode add = Util.createAddOperation(PathAddress.pathAddress(SYSTEM_PROPERTY, OidcBaseTest.class.getName())); + add.get(VALUE).set(clazz.getName()); + ManagementOperations.executeOperation(client.getControllerClient(), add); + } } diff --git a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithDeploymentConfigTest.java b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithDeploymentConfigTest.java index 8bc90daee4d3..1569ffec94b5 100644 --- a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithDeploymentConfigTest.java +++ b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithDeploymentConfigTest.java @@ -24,6 +24,7 @@ import org.jboss.as.test.integration.security.common.Utils; import org.jboss.as.test.integration.security.common.servlets.SimpleSecuredServlet; import org.jboss.as.test.integration.security.common.servlets.SimpleServlet; +import org.jboss.as.version.Stability; import org.jboss.dmr.ModelNode; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.WebArchive; @@ -33,6 +34,8 @@ import org.wildfly.test.integration.elytron.oidc.client.OidcBaseTest; import io.restassured.RestAssured; +import org.wildfly.test.integration.elytron.oidc.client.subsystem.SimpleServletWithScope; +import org.wildfly.test.stabilitylevel.StabilityServerSetupSnapshotRestoreTasks; /** * Tests for the OpenID Connect authentication mechanism. @@ -41,7 +44,7 @@ */ @RunWith(Arquillian.class) @RunAsClient -@ServerSetup({ OidcWithDeploymentConfigTest.KeycloakAndSystemPropertySetup.class }) +@ServerSetup({ OidcWithDeploymentConfigTest.PreviewStabilitySetupTask.class, OidcWithDeploymentConfigTest.KeycloakAndSystemPropertySetup.class }) public class OidcWithDeploymentConfigTest extends OidcBaseTest { private static final String OIDC_PROVIDER_URL = "oidc.provider.url"; @@ -63,6 +66,10 @@ public class OidcWithDeploymentConfigTest extends OidcBaseTest { private static final String BEARER_ONLY_WITH_PROVIDER_URL_FILE = "BearerOnlyWithProviderUrl.json"; private static final String BASIC_AUTH_WITH_PROVIDER_URL_FILE = "BasicAuthWithProviderUrl.json"; private static final String CORS_WITH_PROVIDER_URL_FILE = "CorsWithProviderUrl.json"; + private static final String SINGLE_SCOPE_FILE = "OidcWithSingleScope.json"; + private static final String MULTI_SCOPE_FILE = "OidcWithMultipleScopes.json"; + private static final String INVALID_SCOPE_FILE = "OidcWithInvalidScope.json"; + private static final String OPENID_SCOPE_FILE = "OidcWithOpenIDScope.json"; private static Map APP_NAMES; static { @@ -78,6 +85,14 @@ public class OidcWithDeploymentConfigTest extends OidcBaseTest { APP_NAMES.put(BASIC_AUTH_PROVIDER_URL_APP, KeycloakConfiguration.ClientAppType.BEARER_ONLY_CLIENT); APP_NAMES.put(CORS_PROVIDER_URL_APP, KeycloakConfiguration.ClientAppType.BEARER_ONLY_CLIENT); APP_NAMES.put(CORS_CLIENT, KeycloakConfiguration.ClientAppType.CORS_CLIENT); + APP_NAMES.put(SINGLE_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + APP_NAMES.put(MULTIPLE_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + APP_NAMES.put(INVALID_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + APP_NAMES.put(OPENID_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + } + + public OidcWithDeploymentConfigTest() { + super(Stability.PREVIEW); } @ArquillianResource @@ -164,6 +179,42 @@ public static WebArchive createCorsProviderUrlDeployment() { .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), CORS_WITH_PROVIDER_URL_FILE, "oidc.json"); } + @Deployment(name = SINGLE_SCOPE_APP, managed = false, testable = false) + public static WebArchive createSingleScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, SINGLE_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class) + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), SINGLE_SCOPE_FILE, "oidc.json"); + } + + @Deployment(name = MULTIPLE_SCOPE_APP, managed = false, testable = false) + public static WebArchive createMultipleScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, MULTIPLE_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class) + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), MULTI_SCOPE_FILE, "oidc.json"); + } + + @Deployment(name = INVALID_SCOPE_APP, managed = false, testable = false) + public static WebArchive createInvalidScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, INVALID_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class) + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), INVALID_SCOPE_FILE, "oidc.json"); + } + + @Deployment(name = OPENID_SCOPE_APP, managed = false, testable = false) + public static WebArchive createOpenIdScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, OPENID_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class) + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") + .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OPENID_SCOPE_FILE, "oidc.json"); + } + @Test @InSequence(1) public void testWrongPasswordWithProviderUrl() throws Exception { @@ -381,6 +432,46 @@ public void testCorsRequestWithEnableCorsWithInvalidOrigin() throws Exception { } } + @Test + public void testOpenIDScope() throws Exception { + try{ + deployer.deploy(OPENID_SCOPE_APP); + super.testOpenIDScope(); + } finally { + deployer.undeploy(OPENID_SCOPE_APP); + } + } + + @Test + public void testSingleScope() throws Exception { + try { + deployer.deploy(SINGLE_SCOPE_APP); + super.testSingleScope(); + } finally { + deployer.undeploy(SINGLE_SCOPE_APP); + } + } + + @Test + public void testMultipleScope() throws Exception { + try { + deployer.deploy(MULTIPLE_SCOPE_APP); + super.testMultipleScope(); + } finally { + deployer.undeploy(MULTIPLE_SCOPE_APP); + } + } + + @Test + public void testInvalidScope() throws Exception { + try { + deployer.deploy(INVALID_SCOPE_APP); + super.testInvalidScope(); + } finally { + deployer.undeploy(INVALID_SCOPE_APP); + } + } + static class KeycloakAndSystemPropertySetup extends KeycloakSetup { @Override @@ -422,4 +513,13 @@ public void tearDown(ManagementClient managementClient, String containerId) thro Utils.applyUpdate(operation, client); } } + + public static class PreviewStabilitySetupTask extends StabilityServerSetupSnapshotRestoreTasks.Preview { + @Override + protected void doSetup(ManagementClient managementClient) throws Exception { + // Write a system property so the model gets stored with a lower stability level. + // This is to make sure we can reload back to the higher level from the snapshot + OidcBaseTest.addSystemProperty(managementClient, OidcWithDeploymentConfigTest.class); + } + } } diff --git a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/subsystem/OidcWithSubsystemConfigTest.java b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/subsystem/OidcWithSubsystemConfigTest.java index 0fa87049bcba..a6fca2c796f8 100644 --- a/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/subsystem/OidcWithSubsystemConfigTest.java +++ b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/subsystem/OidcWithSubsystemConfigTest.java @@ -24,6 +24,7 @@ import org.jboss.as.test.integration.security.common.servlets.SimpleSecuredServlet; import org.jboss.as.test.integration.security.common.servlets.SimpleServlet; import org.jboss.as.test.shared.ServerReload; +import org.jboss.as.version.Stability; import org.jboss.dmr.ModelNode; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.WebArchive; @@ -34,6 +35,7 @@ import org.wildfly.test.integration.elytron.oidc.client.OidcBaseTest; import io.restassured.RestAssured; +import org.wildfly.test.stabilitylevel.StabilityServerSetupSnapshotRestoreTasks; /** * Tests for the OpenID Connect authentication mechanism. @@ -42,7 +44,7 @@ */ @RunWith(Arquillian.class) @RunAsClient -@ServerSetup({ OidcWithSubsystemConfigTest.KeycloakAndSubsystemSetup.class }) +@ServerSetup({ OidcWithSubsystemConfigTest.PreviewStabilitySetupTask.class, OidcWithSubsystemConfigTest.KeycloakAndSubsystemSetup.class }) public class OidcWithSubsystemConfigTest extends OidcBaseTest { private static final String SUBSYSTEM_OVERRIDE_APP = "SubsystemOverrideOidcApp"; @@ -66,6 +68,14 @@ public class OidcWithSubsystemConfigTest extends OidcBaseTest { APP_NAMES.put(BASIC_AUTH_PROVIDER_URL_APP, KeycloakConfiguration.ClientAppType.BEARER_ONLY_CLIENT); APP_NAMES.put(CORS_PROVIDER_URL_APP, KeycloakConfiguration.ClientAppType.BEARER_ONLY_CLIENT); APP_NAMES.put(CORS_CLIENT, KeycloakConfiguration.ClientAppType.CORS_CLIENT); + APP_NAMES.put(SINGLE_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + APP_NAMES.put(MULTIPLE_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + APP_NAMES.put(INVALID_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + APP_NAMES.put(OPENID_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_CLIENT); + } + + public OidcWithSubsystemConfigTest() { + super(Stability.PREVIEW); } @Deployment(name = PROVIDER_URL_APP) @@ -132,6 +142,34 @@ public static WebArchive createCorsProviderUrlDeployment() { .addClasses(SimpleSecuredServlet.class); } + @Deployment(name = SINGLE_SCOPE_APP) + public static WebArchive createSingleScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, SINGLE_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class); + } + + @Deployment(name = MULTIPLE_SCOPE_APP) + public static WebArchive createMultipleScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, MULTIPLE_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class); + } + + @Deployment(name = INVALID_SCOPE_APP) + public static WebArchive createInvalidScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, INVALID_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class); + } + + @Deployment(name = OPENID_SCOPE_APP) + public static WebArchive createOpenIdScopeDeployment() { + return ShrinkWrap.create(WebArchive.class, OPENID_SCOPE_APP + ".war") + .addClasses(SimpleServlet.class) + .addClasses(SimpleServletWithScope.class); + } + @Test @OperateOnDeployment(SUBSYSTEM_OVERRIDE_APP) public void testSubsystemOverride() throws Exception { @@ -247,6 +285,55 @@ public void setup(ManagementClient managementClient, String containerId) throws operation.get("enable-cors").set("true"); Utils.applyUpdate(operation, client); + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + MULTIPLE_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); + operation.get("client-id").set(MULTIPLE_SCOPE_APP); + operation.get("public-client").set(false); + operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); + operation.get("ssl-required").set("EXTERNAL"); + operation.get("scope").set("profile email phone microprofile-jwt"); + Utils.applyUpdate(operation, client); + + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + MULTIPLE_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); + operation.get("secret").set("secret"); + Utils.applyUpdate(operation, client); + + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + INVALID_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); + operation.get("client-id").set(INVALID_SCOPE_APP); + operation.get("public-client").set(false); + operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); + operation.get("ssl-required").set("EXTERNAL"); + operation.get("scope").set("INVALID_SCOPE"); + Utils.applyUpdate(operation, client); + + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + INVALID_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); + operation.get("secret").set("secret"); + Utils.applyUpdate(operation, client); + + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + OPENID_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); + operation.get("client-id").set(OPENID_SCOPE_APP); + operation.get("public-client").set(false); + operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); + operation.get("ssl-required").set("EXTERNAL"); + operation.get("scope").set("openid"); + Utils.applyUpdate(operation, client); + + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + OPENID_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); + operation.get("secret").set("secret"); + Utils.applyUpdate(operation, client); + + + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + SINGLE_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); + operation.get("client-id").set(SINGLE_SCOPE_APP); + operation.get("public-client").set(false); + operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); + operation.get("ssl-required").set("EXTERNAL"); + operation.get("scope").set("profile"); + Utils.applyUpdate(operation, client); + + operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + SINGLE_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); + operation.get("secret").set("secret"); + Utils.applyUpdate(operation, client); + ServerReload.executeReloadAndWaitForCompletion(managementClient); } @@ -285,4 +372,13 @@ private static void removeRealm(ModelControllerClient client, String realm) thro Utils.applyUpdate(operation, client); } } + + public static class PreviewStabilitySetupTask extends StabilityServerSetupSnapshotRestoreTasks.Preview { + @Override + protected void doSetup(ManagementClient managementClient) throws Exception { + // Write a system property so the model gets stored with a lower stability level. + // This is to make sure we can reload back to the higher level from the snapshot + OidcBaseTest.addSystemProperty(managementClient, OidcWithSubsystemConfigTest.class); + } + } } diff --git a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/subsystem/SimpleServletWithScope.java b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/subsystem/SimpleServletWithScope.java similarity index 95% rename from testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/subsystem/SimpleServletWithScope.java rename to testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/subsystem/SimpleServletWithScope.java index fca2c955cfec..3aaff8c453a5 100644 --- a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/subsystem/SimpleServletWithScope.java +++ b/testsuite/integration/elytron-oidc-client/src/test/java/org/wildfly/test/integration/elytron/oidc/client/subsystem/SimpleServletWithScope.java @@ -2,7 +2,7 @@ * Copyright The WildFly Authors * SPDX-License-Identifier: Apache-2.0 */ -package org.wildfly.test.manual.elytron.oidc.subsystem; +package org.wildfly.test.integration.elytron.oidc.client.subsystem; import jakarta.annotation.security.DeclareRoles; import jakarta.servlet.annotation.HttpConstraint; @@ -15,9 +15,11 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import org.wildfly.security.http.oidc.OidcSecurityContext; + import org.jboss.as.test.integration.security.common.servlets.SimpleServlet; -import org.wildfly.test.manual.elytron.oidc.KeycloakConfiguration; +import org.wildfly.security.http.oidc.OidcSecurityContext; +import org.wildfly.test.integration.elytron.oidc.client.KeycloakConfiguration; + /** diff --git a/testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithInvalidScope.json b/testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithInvalidScope.json similarity index 100% rename from testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithInvalidScope.json rename to testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithInvalidScope.json diff --git a/testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithMultipleScopes.json b/testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithMultipleScopes.json similarity index 100% rename from testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithMultipleScopes.json rename to testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithMultipleScopes.json diff --git a/testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithOpenIDScope.json b/testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithOpenIDScope.json similarity index 100% rename from testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithOpenIDScope.json rename to testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithOpenIDScope.json diff --git a/testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithSingleScope.json b/testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithSingleScope.json similarity index 100% rename from testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithSingleScope.json rename to testsuite/integration/elytron-oidc-client/src/test/resources/org/wildfly/test/integration/elytron/oidc/client/deployment/OidcWithSingleScope.json diff --git a/testsuite/integration/manualmode/pom.xml b/testsuite/integration/manualmode/pom.xml index b1913c318fc3..1db0e738be09 100644 --- a/testsuite/integration/manualmode/pom.xml +++ b/testsuite/integration/manualmode/pom.xml @@ -41,11 +41,6 @@ - - io.rest-assured - rest-assured - test - jakarta.activation jakarta.activation-api @@ -101,35 +96,16 @@ jboss-jakarta-xml-ws-api_4.0_spec test - - org.jsoup - jsoup - test - org.jgroups jgroups test - - org.keycloak - keycloak-admin-client - test - - - org.keycloak - keycloak-core - test - org.wildfly wildfly-naming-client test - - org.wildfly - wildfly-elytron-oidc-client-subsystem - commons-io commons-io diff --git a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakConfiguration.java b/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakConfiguration.java deleted file mode 100644 index 5d5e18d04a97..000000000000 --- a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakConfiguration.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.wildfly.test.manual.elytron.oidc; - -import static org.wildfly.test.manual.elytron.oidc.OidcBaseTest.MULTIPLE_SCOPE_APP; -import static org.wildfly.test.manual.elytron.oidc.OidcBaseTest.SINGLE_SCOPE_APP; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.keycloak.representations.AccessTokenResponse; -import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.representations.idm.RoleRepresentation; -import org.keycloak.representations.idm.RolesRepresentation; -import org.keycloak.representations.idm.UserRepresentation; - -import io.restassured.RestAssured; -import io.restassured.response.Response; -import io.restassured.specification.RequestSpecification; - -/** - * Keycloak configuration for testing. - * - * @author Prarthona Paul - */ -public class KeycloakConfiguration { - - public static final String USER_ROLE = "user"; - public static final String JBOSS_ADMIN_ROLE = "JBossAdmin"; - public static final String ALICE = "alice"; - public static final String ALICE_PASSWORD = "alice123+"; - public static final String BOB = "bob"; - public static final String BOB_PASSWORD = "bob123+"; - public static final String CHARLIE = "charlie"; - public static final String CHARLIE_PASSWORD = "charlie123+"; - public static final String ALICE_FIRST_NAME = "Alice"; - public static final String ALICE_LAST_NAME = "Smith"; - public static final boolean ALICE_EMAIL_VERIFIED = true; - - public enum ClientAppType { - OIDC_SCOPE_CLIENT - } - - /** - * Configure RealmRepresentation as follows: - *
    - *
  • Two realm roles ("JBossAdmin", "user")
  • - *
  • Two users:
  • - *
      - *
    • user named alice and password alice123+ with "JBossAdmin" and "user" role
    • - *
    • user named bob and password bob123+ with "user" role
    • - *
    - *
- */ - public static RealmRepresentation getRealmRepresentation(final String realmName, String clientSecret, - String clientHostName, int clientPort, Map clientApps) { - return createRealm(realmName, clientSecret, clientHostName, clientPort, clientApps); - } - - public static String getAdminAccessToken(String authServerUrl) { - RequestSpecification requestSpecification = RestAssured - .given() - .param("grant_type", "password") - .param("username", KeycloakContainer.ADMIN_USER) - .param("password", KeycloakContainer.ADMIN_PASSWORD) - .param("client_id", "admin-cli"); - - Response response = requestSpecification.when().post(authServerUrl + "/realms/master/protocol/openid-connect/token"); - - final long deadline = System.currentTimeMillis() + 180000; - while (response.getStatusCode() != 200) { - // the Keycloak admin user isn't available yet, keep trying until it is to ensure we can obtain the token - // needed to set up the realms for the test - response = requestSpecification.when().post(authServerUrl + "/realms/master/protocol/openid-connect/token"); - if (System.currentTimeMillis() > deadline) { - return null; - } - } - - return response.as(AccessTokenResponse.class).getToken(); - } - - private static RealmRepresentation createRealm(String name, String clientSecret, - String clientHostName, int clientPort, Map clientApps) { - RealmRepresentation realm = new RealmRepresentation(); - - realm.setRealm(name); - realm.setEnabled(true); - realm.setUsers(new ArrayList<>()); - realm.setClients(new ArrayList<>()); - realm.setAccessTokenLifespan(3); - realm.setSsoSessionMaxLifespan(3); - - RolesRepresentation roles = new RolesRepresentation(); - List realmRoles = new ArrayList<>(); - - roles.setRealm(realmRoles); - realm.setRoles(roles); - - realm.getRoles().getRealm().add(new RoleRepresentation(USER_ROLE, null, false)); - realm.getRoles().getRealm().add(new RoleRepresentation(JBOSS_ADMIN_ROLE, null, false)); - - for (Map.Entry entry : clientApps.entrySet()) { - String clientApp = entry.getKey(); - ClientRepresentation clientRepresentation = createWebAppClient(clientApp, clientSecret, clientHostName, clientPort, clientApp, false); - realm.getClients().add(clientRepresentation); - } - - realm.getUsers().add(createUser(ALICE, ALICE_PASSWORD, Arrays.asList(USER_ROLE, JBOSS_ADMIN_ROLE), ALICE_FIRST_NAME, ALICE_LAST_NAME, ALICE_EMAIL_VERIFIED)); - realm.getUsers().add(createUser(BOB, BOB_PASSWORD, Arrays.asList(USER_ROLE))); - realm.getUsers().add(createUser(CHARLIE, CHARLIE_PASSWORD, Arrays.asList(USER_ROLE, JBOSS_ADMIN_ROLE))); - return realm; - } - - private static ClientRepresentation createWebAppClient(String clientId, String clientSecret, String clientHostName, int clientPort, - String clientApp, boolean directAccessGrantEnabled) { - return createWebAppClient(clientId, clientSecret, clientHostName, clientPort, clientApp, directAccessGrantEnabled, null); - } - - private static ClientRepresentation createWebAppClient(String clientId, String clientSecret, String clientHostName, int clientPort, - String clientApp, boolean directAccessGrantEnabled, String allowedOrigin) { - ClientRepresentation client = new ClientRepresentation(); - client.setClientId(clientId); - client.setPublicClient(false); - client.setSecret(clientSecret); - //client.setRedirectUris(Arrays.asList("*")); - client.setRedirectUris(Arrays.asList("http://" + clientHostName + ":" + clientPort + "/" + clientApp + "/*")); - client.setEnabled(true); - if (clientId.equals(MULTIPLE_SCOPE_APP) || clientId.equals(SINGLE_SCOPE_APP)) { - client.setOptionalClientScopes(new ArrayList<>()); - client.setDefaultClientScopes(new ArrayList<>()); - client.getDefaultClientScopes().add("web-origins"); - client.getDefaultClientScopes().add("acr"); - client.getOptionalClientScopes().add("address"); - client.getOptionalClientScopes().add("email"); - client.getOptionalClientScopes().add("profile"); - client.getOptionalClientScopes().add("phone"); - client.getDefaultClientScopes().add("roles"); - client.getOptionalClientScopes().add("offline_access"); - client.getOptionalClientScopes().add("microprofile-jwt"); - } - client.setDirectAccessGrantsEnabled(directAccessGrantEnabled); - if (allowedOrigin != null) { - client.setWebOrigins(Collections.singletonList(allowedOrigin)); - } - return client; - } - - private static UserRepresentation createUser(String username, String password, List realmRoles) { - return createUser(username, password, realmRoles, username, null, false); - } - - private static UserRepresentation createUser(String username, String password, List realmRoles, String firstName, String lastName, Boolean emailVerified) { - UserRepresentation user = new UserRepresentation(); - user.setUsername(username); - user.setFirstName(firstName); - user.setLastName(lastName); - user.setEnabled(true); - user.setCredentials(new ArrayList<>()); - user.setRealmRoles(realmRoles); - user.setEmail(username + "@gmail.com"); - user.setEmailVerified(emailVerified); - - CredentialRepresentation credential = new CredentialRepresentation(); - credential.setType(CredentialRepresentation.PASSWORD); - credential.setValue(password); - credential.setTemporary(false); - user.getCredentials().add(credential); - return user; - } - -} \ No newline at end of file diff --git a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakContainer.java b/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakContainer.java deleted file mode 100644 index f2dbcb0beaa7..000000000000 --- a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/KeycloakContainer.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.wildfly.test.manual.elytron.oidc; - -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; - -/** - * KeycloakContainer for testing. - * - * @author Prarthona Paul - */ -public class KeycloakContainer extends GenericContainer { - public static final String ADMIN_USER = "admin"; - public static final String ADMIN_PASSWORD = "admin"; - - private static final String KEYCLOAK_IMAGE = "quay.io/keycloak/keycloak:24.0.1"; - private static final String SSO_IMAGE = System.getProperty("testsuite.integration.oidc.rhsso.image",KEYCLOAK_IMAGE); - private static final int PORT_HTTP = 8080; - private static final int PORT_HTTPS = 8443; - - private boolean useHttps; - - public KeycloakContainer() { - this(false); - } - - public KeycloakContainer(final boolean useHttps) { - super(SSO_IMAGE); - this.useHttps = useHttps; - } - - @Override - protected void configure() { - withExposedPorts(PORT_HTTP, PORT_HTTPS); - withEnv("KEYCLOAK_ADMIN", ADMIN_USER); - withEnv("KEYCLOAK_ADMIN_PASSWORD", ADMIN_PASSWORD); - withEnv("SSO_ADMIN_USERNAME", ADMIN_USER); - withEnv("SSO_ADMIN_PASSWORD", ADMIN_PASSWORD); - if (isUsedRHSSOImage()) { - waitingFor(Wait.forHttp("/auth").forPort(PORT_HTTP)); - }else{ - waitingFor(Wait.forLogMessage(".*Keycloak.*started.*", 1)); - withCommand("start-dev"); - } - } - - public String getAuthServerUrl() { - Integer port = useHttps ? getMappedPort(PORT_HTTPS) : getMappedPort(PORT_HTTP); - String authServerUrl = String.format("http://%s:%s", getContainerIpAddress(), port); - if(isUsedRHSSOImage()){ - authServerUrl += "/auth"; - } - return authServerUrl; - } - - private boolean isUsedRHSSOImage(){ - return SSO_IMAGE.contains("rh-sso"); - } -} \ No newline at end of file diff --git a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/OidcBaseTest.java b/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/OidcBaseTest.java deleted file mode 100644 index 1bb5d440d5e4..000000000000 --- a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/OidcBaseTest.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.wildfly.test.manual.elytron.oidc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; -import static org.wildfly.security.http.oidc.Oidc.OIDC_SCOPE; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.LinkedList; -import java.util.List; - -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.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.HttpClientUtils; -import org.apache.http.impl.client.BasicCookieStore; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.LaxRedirectStrategy; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.HttpContext; -import org.jboss.arquillian.container.test.api.ContainerController; -import org.jboss.arquillian.container.test.api.OperateOnDeployment; -import org.jboss.arquillian.junit.InSequence; -import org.jboss.as.arquillian.api.ServerSetupTask; -import org.jboss.as.arquillian.container.ManagementClient; -import org.jboss.arquillian.test.api.ArquillianResource; -import org.jboss.as.test.http.util.TestHttpClientUtils; -import org.jboss.as.test.integration.security.common.servlets.SimpleServlet; -import org.jboss.as.test.shared.TestSuiteEnvironment; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.junit.BeforeClass; -import org.junit.Test; -import org.keycloak.representations.idm.RealmRepresentation; -import org.testcontainers.DockerClientFactory; -import org.wildfly.security.jose.util.JsonSerialization; - -import io.restassured.RestAssured; -import org.wildfly.test.manual.elytron.oidc.subsystem.SimpleServletWithScope; - -/** - * Tests for the OpenID Connect authentication mechanism. - * - * @author Prarthona Paul - */ -public abstract class OidcBaseTest { - - public static final String CLIENT_SECRET = "secret"; - // TODO migrate this to testsuite/integration/basic and drop the ContainerController aspect used in manualmode - public static final String CONTAINER = "stability-preview"; - public static final String OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML = "web.xml"; - public static KeycloakContainer KEYCLOAK_CONTAINER; - public static final String TEST_REALM = "WildFly"; - private static final String KEYCLOAK_USERNAME = "username"; - private static final String KEYCLOAK_PASSWORD = "password"; - public static final int CLIENT_PORT = TestSuiteEnvironment.getHttpPort(); - public static final String CLIENT_HOST_NAME = TestSuiteEnvironment.getHttpAddress(); - public static final String OPENID_SCOPE_APP = "OpenIDScopeApp"; - public static final String INVALID_SCOPE_APP = "InvalidScopeApp"; - public static final String SINGLE_SCOPE_APP = "SingleScopeApp"; - public static final String MULTIPLE_SCOPE_APP = "MultipleScopeApp"; - - @ArquillianResource - private static ContainerController containerController; - private static boolean isDockerAvailable() { - try { - DockerClientFactory.instance().client(); - return true; - } catch (Throwable ex) { - return false; - } - } - - public static void sendRealmCreationRequest(RealmRepresentation realm) { - try { - String adminAccessToken = KeycloakConfiguration.getAdminAccessToken(KEYCLOAK_CONTAINER.getAuthServerUrl()); - assertNotNull(adminAccessToken); - RestAssured - .given() - .auth().oauth2(adminAccessToken) - .contentType("application/json") - .body(JsonSerialization.writeValueAsBytes(realm)) - .when() - .post(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/admin/realms").then() - .statusCode(201); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @BeforeClass - public static void checkDockerAvailability() { - assumeTrue("Docker isn't available, OIDC tests will be skipped", isDockerAvailable()); - } - - @Test - @InSequence(-1) - public void startContainer() throws Exception { - containerController.start(CONTAINER); - } - - /** - * Tests that use different scope values to request access to claims values. - */ - - @Test - @OperateOnDeployment(OPENID_SCOPE_APP) - public void testOpenIDScope() throws Exception { - String expectedScope = OIDC_SCOPE; - loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, true, - new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), - "/" + OPENID_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, false); - } - - @Test - @OperateOnDeployment(SINGLE_SCOPE_APP) - public void testSingleScope() throws Exception { - String expectedScope = OIDC_SCOPE + "+profile"; - loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, true, - new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), - "/" + SINGLE_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, false); - } - - @Test - @OperateOnDeployment(MULTIPLE_SCOPE_APP) - public void testMultipleScope() throws Exception { - String expectedScope = OIDC_SCOPE + "+phone+profile+microprofile-jwt+email"; - loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, true, - new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), - "/" + MULTIPLE_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, false); - } - - @Test - @OperateOnDeployment(INVALID_SCOPE_APP) - public void testInvalidScope() throws Exception { - String expectedScope = OIDC_SCOPE + "+INVALID_SCOPE"; - loginToApp(KeycloakConfiguration.ALICE, KeycloakConfiguration.ALICE_PASSWORD, HttpURLConnection.HTTP_OK, SimpleServlet.RESPONSE_BODY, false, - new URL("http", TestSuiteEnvironment.getHttpAddress(), TestSuiteEnvironment.getHttpPort(), - "/" + INVALID_SCOPE_APP + SimpleServletWithScope.SERVLET_PATH).toURI(), expectedScope, true); - } - - public static void loginToApp(String username, String password, int expectedStatusCode, String expectedText, boolean loginToKeycloak, URI requestUri, String expectedScope, boolean checkInvalidScope) throws Exception { - CookieStore store = new BasicCookieStore(); - HttpClient httpClient = TestHttpClientUtils.promiscuousCookieHttpClientBuilder() - .setDefaultCookieStore(store) - .setRedirectStrategy(new LaxRedirectStrategy()) - .build(); - HttpGet getMethod = new HttpGet(requestUri); - HttpContext context = new BasicHttpContext(); - HttpResponse response = httpClient.execute(getMethod, context); - - try { - int statusCode = response.getStatusLine().getStatusCode(); - if (loginToKeycloak) { - assertTrue("Expected code == OK but got " + statusCode + " for request=" + requestUri, statusCode == HttpURLConnection.HTTP_OK); - Form keycloakLoginForm = new Form(response); - HttpResponse afterLoginClickResponse = simulateClickingOnButton(httpClient, keycloakLoginForm, username, password, "Sign In"); - afterLoginClickResponse.getEntity().getContent(); - assertEquals(expectedStatusCode, afterLoginClickResponse.getStatusLine().getStatusCode()); - if (expectedText != null) { - String responseString = new BasicResponseHandler().handleResponse(afterLoginClickResponse); - assertTrue("Unexpected result " + responseString, responseString.contains(expectedText)); - if (expectedScope != null) { - assertTrue(context.toString().contains("scope=" + expectedScope)); - if (expectedScope.contains("profile")) { - assertTrue(responseString.contains("profile: " + KeycloakConfiguration.ALICE_FIRST_NAME + " " + KeycloakConfiguration.ALICE_LAST_NAME)); - } - if (expectedScope.contains("email")) { - assertTrue(responseString.contains("email: " + KeycloakConfiguration.ALICE_EMAIL_VERIFIED)); - } - if (expectedScope.contains("microprofile-jwt")) { - assertTrue(responseString.contains("microprofile-jwt: [" + KeycloakConfiguration.JBOSS_ADMIN_ROLE + ", " + KeycloakConfiguration.USER_ROLE + "]")); - } - } - } - } else if (checkInvalidScope) { - assertTrue(context.toString().contains("error_description=Invalid+scopes")); - assertTrue("Expected code == BAD REQUEST but got " + statusCode + " for request=" + requestUri, statusCode == HttpURLConnection.HTTP_BAD_REQUEST); - } else { - assertTrue("Expected code == FORBIDDEN but got " + statusCode + " for request=" + requestUri, statusCode == HttpURLConnection.HTTP_FORBIDDEN); - } - } finally { - HttpClientUtils.closeQuietly(response); - } - } - - public static class KeycloakSetup implements ServerSetupTask { - - @Override - public void setup(ManagementClient managementClient, String containerId) throws Exception { - KEYCLOAK_CONTAINER = new KeycloakContainer(); - KEYCLOAK_CONTAINER.start(); - } - - public void tearDown(ManagementClient managementClient, String containerId) throws Exception { - if (KEYCLOAK_CONTAINER != null) { - KEYCLOAK_CONTAINER.stop(); - } - } - } - - private static HttpResponse simulateClickingOnButton(HttpClient client, Form form, String username, String password, String buttonValue) throws IOException { - final URL url = new URL(form.getAction()); - final HttpPost request = new HttpPost(url.toString()); - final List params = new LinkedList<>(); - for (Input input : form.getInputFields()) { - if (input.type == Input.Type.HIDDEN || - (input.type == Input.Type.SUBMIT && input.getValue().equals(buttonValue))) { - params.add(new BasicNameValuePair(input.getName(), input.getValue())); - } else if (input.getName().equals(KEYCLOAK_USERNAME)) { - params.add(new BasicNameValuePair(input.getName(), username)); - } else if (input.getName().equals(KEYCLOAK_PASSWORD)) { - params.add(new BasicNameValuePair(input.getName(), password)); - } - } - request.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8)); - return client.execute(request); - } - - public static final class Form { - - static final String - NAME = "name", - VALUE = "value", - INPUT = "input", - TYPE = "type", - ACTION = "action", - FORM = "form"; - - final HttpResponse response; - final String action; - final List inputFields = new LinkedList<>(); - - public Form(HttpResponse response) throws IOException { - this.response = response; - final String responseString = new BasicResponseHandler().handleResponse(response); - final Document doc = Jsoup.parse(responseString); - final Element form = doc.select(FORM).first(); - this.action = form.attr(ACTION); - for (Element input : form.select(INPUT)) { - Input.Type type = null; - switch (input.attr(TYPE)) { - case "submit": - type = Input.Type.SUBMIT; - break; - case "hidden": - type = Input.Type.HIDDEN; - break; - } - inputFields.add(new Input(input.attr(NAME), input.attr(VALUE), type)); - } - } - - public String getAction() { - return action; - } - - public List getInputFields() { - return inputFields; - } - } - - private static final class Input { - - final String name, value; - final Input.Type type; - - public Input(String name, String value, Input.Type type) { - this.name = name; - this.value = value; - this.type = type; - } - - public String getName() { - return name; - } - - public String getValue() { - return value; - } - - public enum Type { - HIDDEN, SUBMIT - } - } -} diff --git a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithDeploymentConfigTest.java b/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithDeploymentConfigTest.java deleted file mode 100644 index 947ee28afc1a..000000000000 --- a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/deployment/OidcWithDeploymentConfigTest.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.wildfly.test.manual.elytron.oidc.deployment; - -import java.util.HashMap; -import java.util.Map; - -import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode; -import static org.wildfly.test.manual.elytron.oidc.KeycloakConfiguration.getAdminAccessToken; -import static org.wildfly.test.manual.elytron.oidc.KeycloakConfiguration.getRealmRepresentation; - -import io.restassured.RestAssured; -import org.jboss.arquillian.container.test.api.Deployer; -import org.jboss.arquillian.container.test.api.Deployment; -import org.jboss.arquillian.container.test.api.RunAsClient; -import org.jboss.arquillian.container.test.api.TargetsContainer; -import org.jboss.arquillian.junit.Arquillian; -import org.jboss.arquillian.test.api.ArquillianResource; -import org.jboss.as.arquillian.api.ServerSetup; -import org.jboss.as.arquillian.container.ManagementClient; -import org.jboss.as.controller.client.ModelControllerClient; -import org.jboss.as.controller.descriptions.ModelDescriptionConstants; -import org.jboss.as.test.integration.security.common.Utils; -import org.jboss.as.test.integration.security.common.servlets.SimpleServlet; -import org.jboss.dmr.ModelNode; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.wildfly.test.manual.elytron.oidc.KeycloakConfiguration; -import org.wildfly.test.manual.elytron.oidc.OidcBaseTest; -import org.wildfly.test.manual.elytron.oidc.subsystem.SimpleServletWithScope; - -/** - * Tests for the scope attribute in OpenID Connect authentication - * mechanism using the preview stability level. - * - * @author Prarthona Paul - */ - -@RunWith(Arquillian.class) -@RunAsClient -@ServerSetup({ OidcWithDeploymentConfigTest.KeycloakAndSystemPropertySetup.class }) -public class OidcWithDeploymentConfigTest extends OidcBaseTest { - - private static final String OIDC_PROVIDER_URL = "oidc.provider.url"; - private static final String WRONG_OIDC_PROVIDER_URL = "wrong.oidc.provider.url"; - - private static final String OIDC_AUTH_SERVER_URL = "oidc.auth.server.url"; - private static final String SINGLE_SCOPE_FILE = "OidcWithSingleScope.json"; - private static final String MULTI_SCOPE_FILE = "OidcWithMultipleScopes.json"; - private static final String INVALID_SCOPE_FILE = "OidcWithInvalidScope.json"; - private static final String OPENID_SCOPE_FILE = "OidcWithOpenIDScope.json"; - - private static Map APP_NAMES; - static { - APP_NAMES = new HashMap<>(); - APP_NAMES.put(SINGLE_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_SCOPE_CLIENT); - APP_NAMES.put(MULTIPLE_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_SCOPE_CLIENT); - APP_NAMES.put(INVALID_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_SCOPE_CLIENT); - APP_NAMES.put(OPENID_SCOPE_APP, KeycloakConfiguration.ClientAppType.OIDC_SCOPE_CLIENT); - } - - @ArquillianResource - protected static Deployer deployer; - - @Deployment(name = SINGLE_SCOPE_APP, managed = false, testable = false) - @TargetsContainer(CONTAINER) - public static WebArchive createSingleScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, SINGLE_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class) - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), SINGLE_SCOPE_FILE, "oidc.json"); - } - - @Deployment(name = MULTIPLE_SCOPE_APP, managed = false, testable = false) - @TargetsContainer(CONTAINER) - public static WebArchive createMultipleScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, MULTIPLE_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class) - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), MULTI_SCOPE_FILE, "oidc.json"); - } - - @Deployment(name = INVALID_SCOPE_APP, managed = false, testable = false) - @TargetsContainer(CONTAINER) - public static WebArchive createInvalidScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, INVALID_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class) - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), INVALID_SCOPE_FILE, "oidc.json"); - } - - @Deployment(name = OPENID_SCOPE_APP, managed = false, testable = false) - @TargetsContainer(CONTAINER) - public static WebArchive createOpenIdScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, OPENID_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class) - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OIDC_WITHOUT_SUBSYSTEM_CONFIG_WEB_XML, "web.xml") - .addAsWebInfResource(OidcWithDeploymentConfigTest.class.getPackage(), OPENID_SCOPE_FILE, "oidc.json"); - } - - @Test - public void testOpenIDScope() throws Exception { - try{ - deployer.deploy(OPENID_SCOPE_APP); - super.testOpenIDScope(); - } finally { - deployer.undeploy(OPENID_SCOPE_APP); - } - } - - @Test - public void testSingleScope() throws Exception { - try { - deployer.deploy(SINGLE_SCOPE_APP); - super.testSingleScope(); - } finally { - deployer.undeploy(SINGLE_SCOPE_APP); - } - } - - @Test - public void testMultipleScope() throws Exception { - try { - deployer.deploy(MULTIPLE_SCOPE_APP); - super.testMultipleScope(); - } finally { - deployer.undeploy(MULTIPLE_SCOPE_APP); - } - } - - @Test - public void testInvalidScope() throws Exception { - try { - deployer.deploy(INVALID_SCOPE_APP); - super.testInvalidScope(); - } finally { - deployer.undeploy(INVALID_SCOPE_APP); - } - } - - - static class KeycloakAndSystemPropertySetup extends KeycloakSetup { - @Override - public void setup(ManagementClient managementClient, String containerId) throws Exception { - super.setup(managementClient, containerId); - sendRealmCreationRequest(getRealmRepresentation(TEST_REALM, CLIENT_SECRET, CLIENT_HOST_NAME, CLIENT_PORT, APP_NAMES)); - - ModelControllerClient client = managementClient.getControllerClient(); - ModelNode operation = createOpNode("system-property=" + OIDC_PROVIDER_URL, ModelDescriptionConstants.ADD); - operation.get("value").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM); - Utils.applyUpdate(operation, client); - - operation = createOpNode("system-property=" + OIDC_AUTH_SERVER_URL, ModelDescriptionConstants.ADD); - operation.get("value").set(KEYCLOAK_CONTAINER.getAuthServerUrl()); - Utils.applyUpdate(operation, client); - - operation = createOpNode("system-property=" + WRONG_OIDC_PROVIDER_URL, ModelDescriptionConstants.ADD); - operation.get("value").set("http://fakeauthserver/auth"); // provider url does not exist - Utils.applyUpdate(operation, client); - } - - @Override - public void tearDown(ManagementClient managementClient, String containerId) throws Exception { - RestAssured - .given() - .auth().oauth2(getAdminAccessToken(KEYCLOAK_CONTAINER.getAuthServerUrl())) - .when() - .delete(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/admin/realms/" + TEST_REALM).then().statusCode(204); - - super.tearDown(managementClient, containerId); - ModelControllerClient client = managementClient.getControllerClient(); - ModelNode operation = createOpNode("system-property=" + OIDC_PROVIDER_URL, ModelDescriptionConstants.REMOVE); - Utils.applyUpdate(operation, client); - - operation = createOpNode("system-property=" + OIDC_AUTH_SERVER_URL, ModelDescriptionConstants.REMOVE); - Utils.applyUpdate(operation, client); - - operation = createOpNode("system-property=" + WRONG_OIDC_PROVIDER_URL, ModelDescriptionConstants.REMOVE); - Utils.applyUpdate(operation, client); - } - } -} diff --git a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/subsystem/OidcWithSubsystemConfigTest.java b/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/subsystem/OidcWithSubsystemConfigTest.java deleted file mode 100644 index 6349e9ee4dce..000000000000 --- a/testsuite/integration/manualmode/src/test/java/org/wildfly/test/manual/elytron/oidc/subsystem/OidcWithSubsystemConfigTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ -package org.wildfly.test.manual.elytron.oidc.subsystem; - -import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode; -import static org.wildfly.test.manual.elytron.oidc.KeycloakConfiguration.ClientAppType.OIDC_SCOPE_CLIENT; -import static org.wildfly.test.manual.elytron.oidc.KeycloakConfiguration.getRealmRepresentation; - -import java.util.HashMap; -import java.util.Map; - -import org.jboss.arquillian.container.test.api.Deployment; -import org.jboss.arquillian.container.test.api.RunAsClient; -import org.jboss.arquillian.container.test.api.TargetsContainer; -import org.jboss.arquillian.junit.Arquillian; -import org.jboss.as.arquillian.api.ServerSetup; -import org.jboss.as.arquillian.container.ManagementClient; -import org.jboss.as.controller.client.ModelControllerClient; -import org.jboss.as.controller.descriptions.ModelDescriptionConstants; -import org.jboss.as.test.integration.security.common.Utils; -import org.jboss.as.test.integration.security.common.servlets.SimpleServlet; -import org.jboss.as.test.shared.ServerReload; -import org.jboss.dmr.ModelNode; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.junit.runner.RunWith; - -import io.restassured.RestAssured; -import org.wildfly.extension.elytron.oidc.ElytronOidcExtension; -import org.wildfly.test.manual.elytron.oidc.KeycloakConfiguration; -import org.wildfly.test.manual.elytron.oidc.OidcBaseTest; - -/** - * Tests for the OpenID Connect authentication mechanism. - * - * @author Farah Juma - */ -@RunWith(Arquillian.class) -@RunAsClient -@ServerSetup({ OidcWithSubsystemConfigTest.KeycloakAndSubsystemSetup.class }) -public class OidcWithSubsystemConfigTest extends OidcBaseTest { - - private static final String KEYCLOAK_PROVIDER = "keycloak"; - private static Map APP_NAMES; - private static final String SECURE_DEPLOYMENT_ADDRESS = "subsystem=" + ElytronOidcExtension.SUBSYSTEM_NAME + "/secure-deployment="; - private static final String PROVIDER_ADDRESS = "subsystem=" + ElytronOidcExtension.SUBSYSTEM_NAME + "/provider="; - private static final String REALM_ADDRESS = "subsystem=" + ElytronOidcExtension.SUBSYSTEM_NAME + "/realm="; - - static { - APP_NAMES = new HashMap<>(); - APP_NAMES.put(SINGLE_SCOPE_APP, OIDC_SCOPE_CLIENT); - APP_NAMES.put(MULTIPLE_SCOPE_APP, OIDC_SCOPE_CLIENT); - APP_NAMES.put(INVALID_SCOPE_APP, OIDC_SCOPE_CLIENT); - APP_NAMES.put(OPENID_SCOPE_APP, OIDC_SCOPE_CLIENT); - } - - @Deployment(name = SINGLE_SCOPE_APP) - @TargetsContainer(CONTAINER) - public static WebArchive createSingleScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, SINGLE_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class); - } - - @Deployment(name = MULTIPLE_SCOPE_APP) - @TargetsContainer(CONTAINER) - public static WebArchive createMultipleScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, MULTIPLE_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class); - } - - @Deployment(name = INVALID_SCOPE_APP) - @TargetsContainer(CONTAINER) - public static WebArchive createInvalidScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, INVALID_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class); - } - - @Deployment(name = OPENID_SCOPE_APP) - @TargetsContainer(CONTAINER) - public static WebArchive createOpenIdScopeDeployment() { - return ShrinkWrap.create(WebArchive.class, OPENID_SCOPE_APP + ".war") - .addClasses(SimpleServlet.class) - .addClasses(SimpleServletWithScope.class); - } - - static class KeycloakAndSubsystemSetup extends KeycloakSetup { - - @Override - public void setup(ManagementClient managementClient, String containerId) throws Exception { - super.setup(managementClient, containerId); - sendRealmCreationRequest(getRealmRepresentation(TEST_REALM, CLIENT_SECRET, CLIENT_HOST_NAME, CLIENT_PORT, APP_NAMES)); - - ModelControllerClient client = managementClient.getControllerClient(); - ModelNode operation = createOpNode(PROVIDER_ADDRESS + KEYCLOAK_PROVIDER , ModelDescriptionConstants.ADD); - operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM); - Utils.applyUpdate(operation, client); - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + MULTIPLE_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); - operation.get("client-id").set(MULTIPLE_SCOPE_APP); - operation.get("public-client").set(false); - operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); - operation.get("ssl-required").set("EXTERNAL"); - operation.get("scope").set("profile email phone microprofile-jwt"); - Utils.applyUpdate(operation, client); - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + MULTIPLE_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); - operation.get("secret").set("secret"); - Utils.applyUpdate(operation, client); - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + INVALID_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); - operation.get("client-id").set(INVALID_SCOPE_APP); - operation.get("public-client").set(false); - operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); - operation.get("ssl-required").set("EXTERNAL"); - operation.get("scope").set("INVALID_SCOPE"); - Utils.applyUpdate(operation, client); - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + INVALID_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); - operation.get("secret").set("secret"); - Utils.applyUpdate(operation, client); - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + OPENID_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); - operation.get("client-id").set(OPENID_SCOPE_APP); - operation.get("public-client").set(false); - operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); - operation.get("ssl-required").set("EXTERNAL"); - operation.get("scope").set("openid"); - Utils.applyUpdate(operation, client); - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + OPENID_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); - operation.get("secret").set("secret"); - Utils.applyUpdate(operation, client); - - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + SINGLE_SCOPE_APP + ".war", ModelDescriptionConstants.ADD); - operation.get("client-id").set(SINGLE_SCOPE_APP); - operation.get("public-client").set(false); - operation.get("provider-url").set(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/"); - operation.get("ssl-required").set("EXTERNAL"); - operation.get("scope").set("profile"); - Utils.applyUpdate(operation, client); - - operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + SINGLE_SCOPE_APP + ".war/credential=secret", ModelDescriptionConstants.ADD); - operation.get("secret").set("secret"); - Utils.applyUpdate(operation, client); - - ServerReload.executeReloadAndWaitForCompletion(managementClient); - } - - @Override - public void tearDown(ManagementClient managementClient, String containerId) throws Exception { - ModelControllerClient client = managementClient.getControllerClient(); - for (String appName : APP_NAMES.keySet()) { - removeSecureDeployment(client, appName); - } - - removeProvider(client, KEYCLOAK_PROVIDER); - removeRealm(client, TEST_REALM); - - RestAssured - .given() - .auth().oauth2(KeycloakConfiguration.getAdminAccessToken(KEYCLOAK_CONTAINER.getAuthServerUrl())) - .when() - .delete(KEYCLOAK_CONTAINER.getAuthServerUrl() + "/admin/realms/" + TEST_REALM).then().statusCode(204); - super.tearDown(managementClient, containerId); - } - - private static void removeSecureDeployment(ModelControllerClient client, String name) throws Exception { - ModelNode operation = createOpNode(SECURE_DEPLOYMENT_ADDRESS + name + ".war", ModelDescriptionConstants.REMOVE); - Utils.applyUpdate(operation, client); - } - - private static void removeProvider(ModelControllerClient client, String provider) throws Exception { - ModelNode operation = createOpNode(PROVIDER_ADDRESS + provider, ModelDescriptionConstants.REMOVE); - Utils.applyUpdate(operation, client); - } - - private static void removeRealm(ModelControllerClient client, String realm) throws Exception { - ModelNode operation = createOpNode(REALM_ADDRESS + realm, ModelDescriptionConstants.REMOVE); - Utils.applyUpdate(operation, client); - } - } -} \ No newline at end of file diff --git a/testsuite/integration/manualmode/src/test/resources/arquillian.xml b/testsuite/integration/manualmode/src/test/resources/arquillian.xml index ab404e224403..7f1542163c13 100644 --- a/testsuite/integration/manualmode/src/test/resources/arquillian.xml +++ b/testsuite/integration/manualmode/src/test/resources/arquillian.xml @@ -529,19 +529,6 @@ ${container.java.home} - - - ${oidc.jboss.home} - ${server.jvm.args} - ${jboss.server.config.file.name:standalone.xml} - ${jboss.args} --stability=preview - true - ${node0:127.0.0.1} - ${as.managementPort:9990} - - ${container.java.home} - - diff --git a/testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/web.xml b/testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/web.xml deleted file mode 100644 index 935521cb6d77..000000000000 --- a/testsuite/integration/manualmode/src/test/resources/org/wildfly/test/manual/elytron/oidc/deployment/web.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - OIDC - - -