diff --git a/.github/workflows/quickstart_ejb-security-jwt_ci.yml b/.github/workflows/quickstart_ejb-security-jwt_ci.yml
new file mode 100644
index 0000000000..3254c06b6c
--- /dev/null
+++ b/.github/workflows/quickstart_ejb-security-jwt_ci.yml
@@ -0,0 +1,18 @@
+name: WildFly EJB Security JWT Quickstart CI
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
+ paths:
+ - 'ejb-security-jwt/**'
+ - '.github/workflows/quickstart_ci.yml'
+
+jobs:
+ call-quickstart_ci:
+ uses: ./.github/workflows/quickstart_ci.yml
+ with:
+ QUICKSTART_PATH: ejb-security-jwt
+ TEST_PROVISIONED_SERVER: true
+ TEST_OPENSHIFT: false
+ MATRIX_OS: '"ubuntu-latest"'
+ DEPLOYMENT_DIR: app-one/ear
diff --git a/.github/workflows/quickstart_ejb-security-jwt_ci_before.sh b/.github/workflows/quickstart_ejb-security-jwt_ci_before.sh
new file mode 100755
index 0000000000..b8b6d7d2ed
--- /dev/null
+++ b/.github/workflows/quickstart_ejb-security-jwt_ci_before.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -x
+
+# Start keycloak with required configuration
+docker run -d --rm --name "keycloak" \
+ -p 8180:8080 \
+ -e KEYCLOAK_ADMIN=admin \
+ -e KEYCLOAK_ADMIN_PASSWORD=admin \
+ -v ${GITHUB_WORKSPACE}/quickstarts/ejb-security-jwt/keycloak/realm:/opt/keycloak/data/import \
+ quay.io/keycloak/keycloak:21.0.0 start-dev --import-realm
diff --git a/ejb-security-jwt/README.adoc b/ejb-security-jwt/README.adoc
index e29fcad9eb..e707be1941 100644
--- a/ejb-security-jwt/README.adoc
+++ b/ejb-security-jwt/README.adoc
@@ -312,6 +312,9 @@ We can see that the user `quickstartUser` has the `user` role, but does not have
We can also see that the invocation from EJBA to EJBB uses the same authentication context as what is used in remote client calls EJBA.
+// Server Distribution Testing
+include::../shared-doc/run-integration-tests-with-server-distribution.adoc[leveloffset=+2]
+
== Undeploy the Archives
To undeploy the components from the {productName} servers:
diff --git a/ejb-security-jwt/app-one/ear/pom.xml b/ejb-security-jwt/app-one/ear/pom.xml
index cf01f1bb7e..fc1d257732 100644
--- a/ejb-security-jwt/app-one/ear/pom.xml
+++ b/ejb-security-jwt/app-one/ear/pom.xml
@@ -22,6 +22,7 @@
org.wildfly.quickstarts
ejb-security-jwt-app-one
31.0.0.Beta1-SNAPSHOT
+ ../pom.xml
ejb-security-jwt-app-one-ear
ear
@@ -77,4 +78,47 @@
+
+
+ provisioned-server
+
+
+
+ org.wildfly.plugins
+ wildfly-maven-plugin
+
+
+
+ org.wildfly:wildfly-galleon-pack:${version.server}
+
+
+
+ cloud-server
+ ejb
+
+ ${project.parent.artifactId}.ear
+
+
+ -Dejb-outbound-port=${ejb-outbound-port}
+
+
+
+
+ true
+
+
+
+
+
+
+ package
+
+
+
+
+
+
+
+
+
diff --git a/ejb-security-jwt/client/pom.xml b/ejb-security-jwt/client/pom.xml
index 580ac20dff..a5890ab8a8 100644
--- a/ejb-security-jwt/client/pom.xml
+++ b/ejb-security-jwt/client/pom.xml
@@ -53,6 +53,13 @@
ejb-security-jwt-app-one-ejb
ejb-client
+
+
+
+ junit
+ junit
+ test
+
@@ -74,4 +81,31 @@
+
+
+ integration-testing
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ **/*IT
+
+
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+
+
+
diff --git a/ejb-security-jwt/client/src/test/java/org/jboss/as/quickstarts/ejb/security/jwt/EJBSecurityJWTIT.java b/ejb-security-jwt/client/src/test/java/org/jboss/as/quickstarts/ejb/security/jwt/EJBSecurityJWTIT.java
new file mode 100644
index 0000000000..c73bda81b4
--- /dev/null
+++ b/ejb-security-jwt/client/src/test/java/org/jboss/as/quickstarts/ejb/security/jwt/EJBSecurityJWTIT.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2023 JBoss by Red Hat.
+ *
+ * Licensed 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.jboss.as.quickstarts.ejb.security.jwt;
+
+import org.jboss.as.quickstarts.ejb.security.jwt.appone.JWTSecurityEJBRemoteA;
+import org.jboss.as.quickstarts.ejb.security.jwt.client.RemoteEJBClient;
+import org.junit.Assert;
+import org.junit.Test;
+import org.wildfly.security.auth.client.AuthenticationContext;
+
+import javax.naming.NamingException;
+import java.io.IOException;
+
+/**
+ * Tests that
+ *
+ * @author Lin Gao
+ */
+public class EJBSecurityJWTIT {
+ private static final String DEFAULT_SERVER_HOST = "http://localhost:8080";
+
+ private String getProviderURl() {
+ final String serverHost = System.getProperty("server.host");
+ return "remote+" + (serverHost != null ? serverHost : DEFAULT_SERVER_HOST);
+ }
+
+ @Test
+ public void testRegular() throws NamingException {
+ AuthenticationContext.getContextManager().setThreadDefault(null);
+ JWTSecurityEJBRemoteA remoteA = RemoteEJBClient.lookupEJBRemoteA(true, getProviderURl());
+ Assert.assertEquals("quickstartuser", remoteA.principal().toLowerCase());
+ Assert.assertTrue(remoteA.inRole("user"));
+ Assert.assertFalse(remoteA.inRole("admin"));
+ Assert.assertTrue(remoteA.inRoleFromB("user", true));
+ Assert.assertFalse(remoteA.inRoleFromB("admin", true));
+ }
+
+ @Test
+ public void testAdmin() throws IOException, NamingException {
+ RemoteEJBClient.switchToAdmin();
+ JWTSecurityEJBRemoteA remoteA = RemoteEJBClient.lookupEJBRemoteA(true, getProviderURl());
+ Assert.assertEquals("admin", remoteA.principal().toLowerCase());
+ Assert.assertTrue(remoteA.inRole("user"));
+ Assert.assertTrue(remoteA.inRole("admin"));
+ Assert.assertTrue(remoteA.inRoleFromB("user", true));
+ Assert.assertTrue(remoteA.inRoleFromB("admin", true));
+ }
+
+}
diff --git a/ejb-security-jwt/client/src/test/resources/META-INF/wildfly-config.xml b/ejb-security-jwt/client/src/test/resources/META-INF/wildfly-config.xml
new file mode 100644
index 0000000000..5139f875c0
--- /dev/null
+++ b/ejb-security-jwt/client/src/test/resources/META-INF/wildfly-config.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+