diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index a3a2b7a8ce871..c5c10f5c532ea 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -30,7 +30,7 @@
1.6.0
1.6.0-alpha
1.6.0
- 4.1.1
+ 4.1.2
1.7.4
0.22.0
2.0
diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java
index 40457d081d364..ffabb59f52399 100644
--- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java
+++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java
@@ -42,6 +42,7 @@ public final class OidcUtils {
* ignoring those which are located inside a pair of the double quotes.
*/
private static final Pattern CLAIM_PATH_PATTERN = Pattern.compile("\\/(?=(?:(?:[^\"]*\"){2})*[^\"]*$)");
+ public static final String QUARKUS_IDENTITY_EXPIRE_TIME = "quarkus.identity.expire-time";
private OidcUtils() {
@@ -163,6 +164,7 @@ static QuarkusSecurityIdentity validateAndCreateIdentity(
} catch (InvalidJwtException e) {
throw new AuthenticationFailedException(e);
}
+ builder.addAttribute(QUARKUS_IDENTITY_EXPIRE_TIME, jwtPrincipal.getExpirationTime());
builder.setPrincipal(jwtPrincipal);
setSecurityIdentityRoles(builder, config, rolesJson);
setSecurityIdentityUserInfo(builder, userInfo);
diff --git a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java
index 6b3fb5996d6b2..41d18aa491ee6 100644
--- a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java
+++ b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java
@@ -51,6 +51,7 @@
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.ConfigDescriptionBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
@@ -62,6 +63,7 @@
import io.quarkus.gizmo.MethodCreator;
import io.quarkus.gizmo.MethodDescriptor;
import io.quarkus.gizmo.ResultHandle;
+import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.metrics.MetricsFactory;
import io.quarkus.runtime.util.HashUtil;
import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;
@@ -142,7 +144,8 @@ void collectComponents(BeanDiscoveryFinishedBuildItem beanDiscoveryFinished,
BuildProducer mediatorMethods,
BuildProducer emitters,
BuildProducer channels,
- BuildProducer validationErrors) {
+ BuildProducer validationErrors,
+ BuildProducer configDescriptionBuildItemBuildProducer) {
// We need to collect all business methods annotated with @Incoming/@Outgoing first
for (BeanInfo bean : beanDiscoveryFinished.beanStream().classBeans()) {
@@ -162,10 +165,20 @@ void collectComponents(BeanDiscoveryFinishedBuildItem beanDiscoveryFinished,
validationErrors.produce(new ValidationErrorBuildItem(
new DeploymentException("Empty @Incoming annotation on method " + method)));
}
+ if (incoming != null) {
+ configDescriptionBuildItemBuildProducer.produce(new ConfigDescriptionBuildItem(
+ "mp.messaging.incoming." + incoming.value().asString() + ".connector", String.class, null,
+ "The connector to use", null, null, ConfigPhase.BUILD_TIME));
+ }
if (outgoing != null && outgoing.value().asString().isEmpty()) {
validationErrors.produce(new ValidationErrorBuildItem(
new DeploymentException("Empty @Outgoing annotation on method " + method)));
}
+ if (outgoing != null) {
+ configDescriptionBuildItemBuildProducer.produce(new ConfigDescriptionBuildItem(
+ "mp.messaging.outgoing." + outgoing.value().asString() + ".connector", String.class, null,
+ "The connector to use", null, null, ConfigPhase.BUILD_TIME));
+ }
if (isSynthetic(method.flags())) {
continue;
}
diff --git a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/AnnotatedWebsocketEndpointBuildItem.java b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/AnnotatedWebsocketEndpointBuildItem.java
similarity index 89%
rename from extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/AnnotatedWebsocketEndpointBuildItem.java
rename to extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/AnnotatedWebsocketEndpointBuildItem.java
index 92f3e7a982e26..bd48ee87f995c 100644
--- a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/AnnotatedWebsocketEndpointBuildItem.java
+++ b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/AnnotatedWebsocketEndpointBuildItem.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.client.deployment;
+package io.quarkus.websockets.client.deployment;
import io.quarkus.builder.item.MultiBuildItem;
diff --git a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/ServerWebSocketContainerBuildItem.java b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/ServerWebSocketContainerBuildItem.java
similarity index 90%
rename from extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/ServerWebSocketContainerBuildItem.java
rename to extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/ServerWebSocketContainerBuildItem.java
index 1f0d7b1861ca6..6395347a89935 100644
--- a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/ServerWebSocketContainerBuildItem.java
+++ b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/ServerWebSocketContainerBuildItem.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.client.deployment;
+package io.quarkus.websockets.client.deployment;
import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.runtime.RuntimeValue;
diff --git a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/ServerWebSocketContainerFactoryBuildItem.java b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/ServerWebSocketContainerFactoryBuildItem.java
similarity index 74%
rename from extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/ServerWebSocketContainerFactoryBuildItem.java
rename to extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/ServerWebSocketContainerFactoryBuildItem.java
index 1180537fd65cd..2e4f0d7237bad 100644
--- a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/ServerWebSocketContainerFactoryBuildItem.java
+++ b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/ServerWebSocketContainerFactoryBuildItem.java
@@ -1,7 +1,7 @@
-package io.quarkus.undertow.websockets.client.deployment;
+package io.quarkus.websockets.client.deployment;
import io.quarkus.builder.item.SimpleBuildItem;
-import io.quarkus.undertow.websockets.client.runtime.ServerWebSocketContainerFactory;
+import io.quarkus.websockets.client.runtime.ServerWebSocketContainerFactory;
public final class ServerWebSocketContainerFactoryBuildItem extends SimpleBuildItem {
diff --git a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebSocketDeploymentInfoBuildItem.java b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebSocketDeploymentInfoBuildItem.java
similarity index 89%
rename from extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebSocketDeploymentInfoBuildItem.java
rename to extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebSocketDeploymentInfoBuildItem.java
index 3bcc0d794e577..daadfba2e5c96 100644
--- a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebSocketDeploymentInfoBuildItem.java
+++ b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebSocketDeploymentInfoBuildItem.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.client.deployment;
+package io.quarkus.websockets.client.deployment;
import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.runtime.RuntimeValue;
diff --git a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketClientProcessor.java b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebsocketClientProcessor.java
similarity index 98%
rename from extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketClientProcessor.java
rename to extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebsocketClientProcessor.java
index c38f426a850e0..0d5de63ea0358 100644
--- a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketClientProcessor.java
+++ b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebsocketClientProcessor.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.client.deployment;
+package io.quarkus.websockets.client.deployment;
import java.lang.reflect.Modifier;
import java.util.Collection;
@@ -37,7 +37,7 @@
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.undertow.deployment.ServletContextAttributeBuildItem;
-import io.quarkus.undertow.websockets.client.runtime.WebsocketCoreRecorder;
+import io.quarkus.websockets.client.runtime.WebsocketCoreRecorder;
import io.undertow.websockets.DefaultContainerConfigurator;
import io.undertow.websockets.ServerWebSocketContainer;
import io.undertow.websockets.UndertowContainerProvider;
diff --git a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketConfig.java b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebsocketConfig.java
similarity index 92%
rename from extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketConfig.java
rename to extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebsocketConfig.java
index 4b8cfc95035f8..51a5000d50698 100644
--- a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketConfig.java
+++ b/extensions/websockets/client/deployment/src/main/java/io/quarkus/websockets/client/deployment/WebsocketConfig.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.client.deployment;
+package io.quarkus.websockets.client.deployment;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
diff --git a/extensions/websockets/client/deployment/src/test/java/io/quarkus/undertow/websockets/test/TestWebSocketClient.java b/extensions/websockets/client/deployment/src/test/java/io/quarkus/websockets/test/TestWebSocketClient.java
similarity index 91%
rename from extensions/websockets/client/deployment/src/test/java/io/quarkus/undertow/websockets/test/TestWebSocketClient.java
rename to extensions/websockets/client/deployment/src/test/java/io/quarkus/websockets/test/TestWebSocketClient.java
index 4d0c779e19e9d..83744638f7a29 100644
--- a/extensions/websockets/client/deployment/src/test/java/io/quarkus/undertow/websockets/test/TestWebSocketClient.java
+++ b/extensions/websockets/client/deployment/src/test/java/io/quarkus/websockets/test/TestWebSocketClient.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.test;
+package io.quarkus.websockets.test;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
diff --git a/extensions/websockets/client/deployment/src/test/java/io/quarkus/undertow/websockets/test/WebSocketClientTestCase.java b/extensions/websockets/client/deployment/src/test/java/io/quarkus/websockets/test/WebSocketClientTestCase.java
similarity index 98%
rename from extensions/websockets/client/deployment/src/test/java/io/quarkus/undertow/websockets/test/WebSocketClientTestCase.java
rename to extensions/websockets/client/deployment/src/test/java/io/quarkus/websockets/test/WebSocketClientTestCase.java
index 5db5d366406b7..19824dc551894 100644
--- a/extensions/websockets/client/deployment/src/test/java/io/quarkus/undertow/websockets/test/WebSocketClientTestCase.java
+++ b/extensions/websockets/client/deployment/src/test/java/io/quarkus/websockets/test/WebSocketClientTestCase.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.test;
+package io.quarkus.websockets.test;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
diff --git a/extensions/websockets/client/runtime/pom.xml b/extensions/websockets/client/runtime/pom.xml
index 25d6e7d215fe5..4e508412af5d6 100644
--- a/extensions/websockets/client/runtime/pom.xml
+++ b/extensions/websockets/client/runtime/pom.xml
@@ -23,6 +23,10 @@
io.quarkus
quarkus-vertx
+
+ io.quarkus.security
+ quarkus-security
+
jakarta.websocket
jakarta.websocket-api
diff --git a/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/BearerTokenClientEndpointConfigurator.java b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/BearerTokenClientEndpointConfigurator.java
new file mode 100644
index 0000000000000..ede94928dc32d
--- /dev/null
+++ b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/BearerTokenClientEndpointConfigurator.java
@@ -0,0 +1,56 @@
+package io.quarkus.websockets;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.websocket.ClientEndpointConfig;
+import javax.websocket.Decoder;
+import javax.websocket.Encoder;
+import javax.websocket.Extension;
+
+import io.vertx.core.http.HttpHeaders;
+
+public class BearerTokenClientEndpointConfigurator implements ClientEndpointConfig {
+
+ final String token;
+
+ public BearerTokenClientEndpointConfigurator(String token) {
+ this.token = token;
+ }
+
+ @Override
+ public List getPreferredSubprotocols() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Configurator getConfigurator() {
+ return new Configurator() {
+ @Override
+ public void beforeRequest(Map> headers) {
+ headers.put(HttpHeaders.AUTHORIZATION.toString(), Collections.singletonList("Bearer " + token));
+ }
+ };
+ }
+
+ @Override
+ public List> getEncoders() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List> getDecoders() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Map getUserProperties() {
+ return Collections.emptyMap();
+ }
+}
diff --git a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/ExecutorSupplier.java b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/ExecutorSupplier.java
similarity index 82%
rename from extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/ExecutorSupplier.java
rename to extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/ExecutorSupplier.java
index a4905686beb0b..afe8accd528f1 100644
--- a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/ExecutorSupplier.java
+++ b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/ExecutorSupplier.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.client.runtime;
+package io.quarkus.websockets.client.runtime;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
diff --git a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/ServerWebSocketContainerFactory.java b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/ServerWebSocketContainerFactory.java
similarity index 83%
rename from extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/ServerWebSocketContainerFactory.java
rename to extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/ServerWebSocketContainerFactory.java
index 2f545ca292155..57e610501c831 100644
--- a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/ServerWebSocketContainerFactory.java
+++ b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/ServerWebSocketContainerFactory.java
@@ -1,6 +1,7 @@
-package io.quarkus.undertow.websockets.client.runtime;
+package io.quarkus.websockets.client.runtime;
import java.net.InetSocketAddress;
+import java.security.Principal;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
@@ -17,5 +18,6 @@ public interface ServerWebSocketContainerFactory {
ServerWebSocketContainer create(ObjectIntrospecter objectIntrospecter, ClassLoader classLoader,
Supplier eventLoopSupplier, List contextSetupHandlers,
boolean dispatchToWorker, InetSocketAddress clientBindAddress, WebSocketReconnectHandler reconnectHandler,
- Supplier executorSupplier, List installedExtensions, int maxFrameSize);
+ Supplier executorSupplier, List installedExtensions, int maxFrameSize,
+ Supplier currentUserSupplier);
}
diff --git a/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/WebSocketPrincipal.java b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/WebSocketPrincipal.java
new file mode 100644
index 0000000000000..f364c20807bce
--- /dev/null
+++ b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/WebSocketPrincipal.java
@@ -0,0 +1,24 @@
+package io.quarkus.websockets.client.runtime;
+
+import java.security.Principal;
+
+import io.quarkus.security.identity.SecurityIdentity;
+
+public class WebSocketPrincipal implements Principal {
+
+ final SecurityIdentity securityIdentity;
+
+ public WebSocketPrincipal(SecurityIdentity securityIdentity) {
+ this.securityIdentity = securityIdentity;
+ }
+
+ @Override
+ public String getName() {
+ return securityIdentity.getPrincipal().getName();
+ }
+
+ public SecurityIdentity getSecurityIdentity() {
+ return securityIdentity;
+ }
+
+}
diff --git a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/WebsocketCoreRecorder.java b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/WebsocketCoreRecorder.java
similarity index 81%
rename from extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/WebsocketCoreRecorder.java
rename to extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/WebsocketCoreRecorder.java
index 1a420478fefb4..93ed683e37a61 100644
--- a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/WebsocketCoreRecorder.java
+++ b/extensions/websockets/client/runtime/src/main/java/io/quarkus/websockets/client/runtime/WebsocketCoreRecorder.java
@@ -1,11 +1,13 @@
-package io.quarkus.undertow.websockets.client.runtime;
+package io.quarkus.websockets.client.runtime;
+import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
+import javax.enterprise.inject.Instance;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
@@ -19,9 +21,11 @@
import io.quarkus.arc.runtime.BeanContainer;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.annotations.Recorder;
+import io.quarkus.security.identity.CurrentIdentityAssociation;
import io.quarkus.vertx.core.runtime.VertxCoreRecorder;
import io.undertow.websockets.ServerWebSocketContainer;
import io.undertow.websockets.UndertowContainerProvider;
+import io.undertow.websockets.UndertowSession;
import io.undertow.websockets.WebSocketDeploymentInfo;
import io.undertow.websockets.util.ContextSetupHandler;
import io.undertow.websockets.util.ObjectFactory;
@@ -115,6 +119,9 @@ public RuntimeValue createServerContainer(BeanContaine
if (serverContainerFactory == null) {
serverContainerFactory = ServerWebSocketContainer::new;
}
+ Instance currentIdentityAssociation = Arc.container()
+ .select(CurrentIdentityAssociation.class);
+
ServerWebSocketContainer container = serverContainerFactory.create(new ObjectIntrospecter() {
@Override
public ObjectFactory createInstanceFactory(Class clazz) {
@@ -147,16 +154,31 @@ public EventLoopGroup get() {
@Override
public Action create(Action action) {
return new Action() {
+
+ CurrentIdentityAssociation getCurrentIdentityAssociation() {
+ if (currentIdentityAssociation.isResolvable()) {
+ return currentIdentityAssociation.get();
+ }
+ return null;
+ }
+
@Override
- public T call(C context) throws Exception {
+ public T call(C context, UndertowSession session) throws Exception {
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(cl);
boolean required = !requestContext.isActive();
if (required) {
requestContext.activate();
+ Principal p = session.getUserPrincipal();
+ if (p instanceof WebSocketPrincipal) {
+ var current = getCurrentIdentityAssociation();
+ if (current != null) {
+ current.setIdentity(((WebSocketPrincipal) p).getSecurityIdentity());
+ }
+ }
}
try {
- return action.call(context);
+ return action.call(context, session);
} finally {
try {
if (required) {
@@ -175,7 +197,15 @@ public T call(C context) throws Exception {
null,
info.getExecutor(),
Collections.emptyList(),
- info.getMaxFrameSize());
+ info.getMaxFrameSize(), new Supplier() {
+ @Override
+ public Principal get() {
+ if (currentIdentityAssociation.isResolvable()) {
+ return new WebSocketPrincipal(currentIdentityAssociation.get().getIdentity());
+ }
+ return null;
+ }
+ });
for (Class> i : info.getAnnotatedEndpoints()) {
container.addEndpoint(i);
}
diff --git a/extensions/websockets/server/deployment/src/main/java/io/quarkus/undertow/websockets/deployment/ServerWebSocketProcessor.java b/extensions/websockets/server/deployment/src/main/java/io/quarkus/websockets/deployment/ServerWebSocketProcessor.java
similarity index 85%
rename from extensions/websockets/server/deployment/src/main/java/io/quarkus/undertow/websockets/deployment/ServerWebSocketProcessor.java
rename to extensions/websockets/server/deployment/src/main/java/io/quarkus/websockets/deployment/ServerWebSocketProcessor.java
index 2094cb293218c..cbff174071b16 100644
--- a/extensions/websockets/server/deployment/src/main/java/io/quarkus/undertow/websockets/deployment/ServerWebSocketProcessor.java
+++ b/extensions/websockets/server/deployment/src/main/java/io/quarkus/websockets/deployment/ServerWebSocketProcessor.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.deployment;
+package io.quarkus.websockets.deployment;
import java.lang.reflect.Modifier;
import java.util.Collection;
@@ -20,13 +20,13 @@
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
-import io.quarkus.undertow.websockets.client.deployment.AnnotatedWebsocketEndpointBuildItem;
-import io.quarkus.undertow.websockets.client.deployment.ServerWebSocketContainerBuildItem;
-import io.quarkus.undertow.websockets.client.deployment.ServerWebSocketContainerFactoryBuildItem;
-import io.quarkus.undertow.websockets.client.deployment.WebSocketDeploymentInfoBuildItem;
-import io.quarkus.undertow.websockets.client.deployment.WebsocketClientProcessor;
-import io.quarkus.undertow.websockets.runtime.WebsocketServerRecorder;
import io.quarkus.vertx.http.deployment.FilterBuildItem;
+import io.quarkus.websockets.client.deployment.AnnotatedWebsocketEndpointBuildItem;
+import io.quarkus.websockets.client.deployment.ServerWebSocketContainerBuildItem;
+import io.quarkus.websockets.client.deployment.ServerWebSocketContainerFactoryBuildItem;
+import io.quarkus.websockets.client.deployment.WebSocketDeploymentInfoBuildItem;
+import io.quarkus.websockets.client.deployment.WebsocketClientProcessor;
+import io.quarkus.websockets.runtime.WebsocketServerRecorder;
public class ServerWebSocketProcessor {
diff --git a/extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/EchoService.java b/extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/EchoService.java
similarity index 77%
rename from extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/EchoService.java
rename to extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/EchoService.java
index 4db7b3e9ad27e..e8258090f203b 100644
--- a/extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/EchoService.java
+++ b/extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/EchoService.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.test;
+package io.quarkus.websockets.test;
import javax.enterprise.context.RequestScoped;
diff --git a/extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/EchoWebSocket.java b/extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/EchoWebSocket.java
similarity index 86%
rename from extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/EchoWebSocket.java
rename to extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/EchoWebSocket.java
index 8af19f7613493..1f5c7a84c4a4b 100644
--- a/extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/EchoWebSocket.java
+++ b/extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/EchoWebSocket.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.test;
+package io.quarkus.websockets.test;
import javax.inject.Inject;
import javax.websocket.OnMessage;
diff --git a/extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/WebsocketDevModeTestCase.java b/extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/WebsocketDevModeTestCase.java
similarity index 98%
rename from extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/WebsocketDevModeTestCase.java
rename to extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/WebsocketDevModeTestCase.java
index 82451f3262efa..7f506a93fe645 100644
--- a/extensions/websockets/server/deployment/src/test/java/io/quarkus/undertow/websockets/test/WebsocketDevModeTestCase.java
+++ b/extensions/websockets/server/deployment/src/test/java/io/quarkus/websockets/test/WebsocketDevModeTestCase.java
@@ -1,4 +1,4 @@
-package io.quarkus.undertow.websockets.test;
+package io.quarkus.websockets.test;
import java.net.URI;
import java.util.concurrent.LinkedBlockingDeque;
diff --git a/extensions/websockets/server/runtime/src/main/java/io/quarkus/undertow/websockets/runtime/WebsocketServerRecorder.java b/extensions/websockets/server/runtime/src/main/java/io/quarkus/undertow/websockets/runtime/WebsocketServerRecorder.java
deleted file mode 100644
index 33a418dfc5f66..0000000000000
--- a/extensions/websockets/server/runtime/src/main/java/io/quarkus/undertow/websockets/runtime/WebsocketServerRecorder.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package io.quarkus.undertow.websockets.runtime;
-
-import java.net.InetSocketAddress;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.function.Supplier;
-
-import javax.websocket.DeploymentException;
-import javax.websocket.Extension;
-
-import org.jboss.logging.Logger;
-
-import io.netty.channel.EventLoopGroup;
-import io.quarkus.runtime.RuntimeValue;
-import io.quarkus.runtime.annotations.Recorder;
-import io.quarkus.undertow.websockets.client.runtime.ServerWebSocketContainerFactory;
-import io.quarkus.undertow.websockets.client.runtime.WebsocketCoreRecorder;
-import io.undertow.websockets.ServerWebSocketContainer;
-import io.undertow.websockets.WebSocketDeploymentInfo;
-import io.undertow.websockets.WebSocketReconnectHandler;
-import io.undertow.websockets.util.ContextSetupHandler;
-import io.undertow.websockets.util.ObjectIntrospecter;
-import io.undertow.websockets.vertx.VertxServerWebSocketContainer;
-import io.undertow.websockets.vertx.VertxWebSocketHandler;
-import io.vertx.core.Handler;
-import io.vertx.ext.web.RoutingContext;
-
-@Recorder
-public class WebsocketServerRecorder {
-
- private static final Logger log = Logger.getLogger(WebsocketCoreRecorder.class);
-
- public Handler createHandler(RuntimeValue info,
- RuntimeValue container) throws DeploymentException {
- return new VertxWebSocketHandler(container.getValue(), info.getValue());
- }
-
- public ServerWebSocketContainerFactory createFactory() {
- return new ServerWebSocketContainerFactory() {
- @Override
- public ServerWebSocketContainer create(ObjectIntrospecter objectIntrospecter, ClassLoader classLoader,
- Supplier eventLoopSupplier, List contextSetupHandlers,
- boolean dispatchToWorker, InetSocketAddress clientBindAddress, WebSocketReconnectHandler reconnectHandler,
- Supplier executorSupplier, List installedExtensions, int maxFrameSize) {
- return new VertxServerWebSocketContainer(objectIntrospecter, classLoader, eventLoopSupplier,
- contextSetupHandlers, dispatchToWorker, clientBindAddress, reconnectHandler, executorSupplier,
- installedExtensions, maxFrameSize);
- }
- };
- }
-}
diff --git a/extensions/websockets/server/runtime/src/main/java/io/quarkus/websockets/runtime/WebsocketServerRecorder.java b/extensions/websockets/server/runtime/src/main/java/io/quarkus/websockets/runtime/WebsocketServerRecorder.java
new file mode 100644
index 0000000000000..7490203995cdf
--- /dev/null
+++ b/extensions/websockets/server/runtime/src/main/java/io/quarkus/websockets/runtime/WebsocketServerRecorder.java
@@ -0,0 +1,104 @@
+package io.quarkus.websockets.runtime;
+
+import java.net.InetSocketAddress;
+import java.security.Principal;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+import javax.websocket.DeploymentException;
+import javax.websocket.Extension;
+
+import org.jboss.logging.Logger;
+
+import io.netty.channel.EventLoopGroup;
+import io.quarkus.arc.Arc;
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+import io.quarkus.security.identity.CurrentIdentityAssociation;
+import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
+import io.quarkus.websockets.client.runtime.ServerWebSocketContainerFactory;
+import io.quarkus.websockets.client.runtime.WebSocketPrincipal;
+import io.quarkus.websockets.client.runtime.WebsocketCoreRecorder;
+import io.undertow.websockets.ServerWebSocketContainer;
+import io.undertow.websockets.WebSocketDeploymentInfo;
+import io.undertow.websockets.WebSocketReconnectHandler;
+import io.undertow.websockets.util.ContextSetupHandler;
+import io.undertow.websockets.util.ObjectIntrospecter;
+import io.undertow.websockets.vertx.VertxServerWebSocketContainer;
+import io.undertow.websockets.vertx.VertxWebSocketHandler;
+import io.undertow.websockets.vertx.VertxWebSocketHttpExchange;
+import io.vertx.core.Handler;
+import io.vertx.core.net.impl.ConnectionBase;
+import io.vertx.ext.web.RoutingContext;
+
+@Recorder
+public class WebsocketServerRecorder {
+
+ private static final Logger log = Logger.getLogger(WebsocketCoreRecorder.class);
+
+ public Handler createHandler(RuntimeValue info,
+ RuntimeValue container) throws DeploymentException {
+ return new VertxWebSocketHandler(container.getValue(), info.getValue()) {
+ @Override
+ protected VertxWebSocketHttpExchange createHttpExchange(RoutingContext event) {
+ return new QuarkusVertxWebSocketHttpExchange(executor, event);
+ }
+ };
+ }
+
+ public ServerWebSocketContainerFactory createFactory() {
+ return new ServerWebSocketContainerFactory() {
+ @Override
+ public ServerWebSocketContainer create(ObjectIntrospecter objectIntrospecter, ClassLoader classLoader,
+ Supplier eventLoopSupplier, List contextSetupHandlers,
+ boolean dispatchToWorker, InetSocketAddress clientBindAddress, WebSocketReconnectHandler reconnectHandler,
+ Supplier executorSupplier, List installedExtensions, int maxFrameSize,
+ Supplier currentUserSupplier) {
+ var identity = Arc.container().instance(CurrentIdentityAssociation.class);
+ return new VertxServerWebSocketContainer(objectIntrospecter, classLoader, eventLoopSupplier,
+ contextSetupHandlers, dispatchToWorker, clientBindAddress, reconnectHandler, executorSupplier,
+ installedExtensions, maxFrameSize, currentUserSupplier) {
+ @Override
+ protected VertxWebSocketHttpExchange createHttpExchange(RoutingContext routingContext) {
+ QuarkusHttpUser user = (QuarkusHttpUser) routingContext.user();
+ if (user != null) {
+ //close the connection when the identity expires
+ Long expire = user.getSecurityIdentity().getAttribute("quarkus.identity.expire-time");
+ if (expire != null) {
+ ((ConnectionBase) routingContext.request().connection()).channel().eventLoop()
+ .schedule(new Runnable() {
+ @Override
+ public void run() {
+ routingContext.request().connection().close();
+ }
+ }, expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
+ }
+ }
+ return new QuarkusVertxWebSocketHttpExchange(getExecutorSupplier().get(), routingContext);
+ }
+ };
+ }
+ };
+ }
+
+ private static class QuarkusVertxWebSocketHttpExchange extends VertxWebSocketHttpExchange {
+
+ private final RoutingContext routingContext;
+
+ public QuarkusVertxWebSocketHttpExchange(Executor executor, RoutingContext routingContext) {
+ super(executor, routingContext);
+ this.routingContext = routingContext;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ QuarkusHttpUser user = (QuarkusHttpUser) routingContext.user();
+ if (user != null) {
+ return new WebSocketPrincipal(user.getSecurityIdentity());
+ }
+ return null;
+ }
+ }
+}
diff --git a/integration-tests/oidc/pom.xml b/integration-tests/oidc/pom.xml
index 37a87f7a9bbcd..e4259d8420468 100644
--- a/integration-tests/oidc/pom.xml
+++ b/integration-tests/oidc/pom.xml
@@ -22,6 +22,10 @@
io.quarkus
quarkus-resteasy-reactive-jackson
+
+ io.quarkus
+ quarkus-websockets
+
io.quarkus
@@ -84,6 +88,19 @@
+
+ io.quarkus
+ quarkus-websockets-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
diff --git a/integration-tests/oidc/src/main/java/io/quarkus/it/keycloak/SecuredHelloWebSocket.java b/integration-tests/oidc/src/main/java/io/quarkus/it/keycloak/SecuredHelloWebSocket.java
new file mode 100644
index 0000000000000..cd6d270ca5ee9
--- /dev/null
+++ b/integration-tests/oidc/src/main/java/io/quarkus/it/keycloak/SecuredHelloWebSocket.java
@@ -0,0 +1,23 @@
+package io.quarkus.it.keycloak;
+
+import javax.annotation.security.RolesAllowed;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.websocket.OnMessage;
+import javax.websocket.server.ServerEndpoint;
+
+import io.quarkus.security.identity.SecurityIdentity;
+
+@ServerEndpoint("/secured-hello")
+@ApplicationScoped
+@RolesAllowed("user")
+public class SecuredHelloWebSocket {
+
+ @Inject
+ SecurityIdentity identity;
+
+ @OnMessage
+ public String onMessage(String message) {
+ return message + " " + identity.getPrincipal().getName();
+ }
+}
diff --git a/integration-tests/oidc/src/test/java/io/quarkus/it/keycloak/WebsocketOidcTestCase.java b/integration-tests/oidc/src/test/java/io/quarkus/it/keycloak/WebsocketOidcTestCase.java
new file mode 100644
index 0000000000000..a8397e06db357
--- /dev/null
+++ b/integration-tests/oidc/src/test/java/io/quarkus/it/keycloak/WebsocketOidcTestCase.java
@@ -0,0 +1,55 @@
+package io.quarkus.it.keycloak;
+
+import static io.quarkus.test.keycloak.server.KeycloakTestResourceLifecycleManager.getAccessToken;
+
+import java.net.URI;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+
+import javax.websocket.ContainerProvider;
+import javax.websocket.Endpoint;
+import javax.websocket.EndpointConfig;
+import javax.websocket.MessageHandler;
+import javax.websocket.Session;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.common.http.TestHTTPResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.keycloak.server.KeycloakTestResourceLifecycleManager;
+import io.quarkus.websockets.BearerTokenClientEndpointConfigurator;
+
+@QuarkusTest
+@QuarkusTestResource(KeycloakTestResourceLifecycleManager.class)
+public class WebsocketOidcTestCase {
+
+ @TestHTTPResource("secured-hello")
+ URI wsUri;
+
+ @Test
+ public void websocketTest() throws Exception {
+
+ LinkedBlockingDeque message = new LinkedBlockingDeque<>();
+ Session session = ContainerProvider.getWebSocketContainer().connectToServer(new Endpoint() {
+ @Override
+ public void onOpen(Session session, EndpointConfig endpointConfig) {
+ session.addMessageHandler(new MessageHandler.Whole() {
+ @Override
+ public void onMessage(String s) {
+ message.add(s);
+ }
+ });
+ session.getAsyncRemote().sendText("hello");
+ }
+ }, new BearerTokenClientEndpointConfigurator(getAccessToken("alice")), wsUri);
+
+ try {
+ Assertions.assertEquals("hello alice@gmail.com", message.poll(20, TimeUnit.SECONDS));
+ } finally {
+ session.close();
+ }
+ }
+
+}