You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Frames should be processed successfully without any exceptions being thrown.
Actual Behaviour
In current version of Micronaut (4.6.3) with enabled security and the @Secured({SecurityRule.IS_AUTHENTICATED}) annotation is applied to a WebSocket server, a ClassCastException is thrown when any type of frame is sent after the onOpen event.
WebSocket server preview:
@Secured({SecurityRule.IS_AUTHENTICATED}) //<--- triggers ClassCastException for any frame send just after onOpen event (client side)@ServerWebSocket("/chat/{topic}/{username}") // (1)publicclassChatServerWebSocket {
// body: https://docs.micronaut.io/latest/guide/#websocketServer
}
the ClassCastException is thrown when any frame is sent after onOpen event. Here is a log output, e.g. from ping frame:
12:42:12.946 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 1513ms. Server Running: http://localhost:8080
12:42:55.629 [default-nioEventLoopGroup-1-2] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
12:42:55.629 [default-nioEventLoopGroup-1-2] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
12:42:55.630 [default-nioEventLoopGroup-1-2] DEBUG i.n.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@416cf938
12:42:55.639 [default-nioEventLoopGroup-1-2] DEBUG i.n.h.c.compression.ZlibCodecFactory - -Dio.netty.noJdkZlibDecoder: false
12:42:55.639 [default-nioEventLoopGroup-1-2] DEBUG i.n.h.c.compression.ZlibCodecFactory - -Dio.netty.noJdkZlibEncoder: false
12:42:55.642 [default-nioEventLoopGroup-1-2] DEBUG i.n.handler.codec.compression.Brotli - brotli4j not in the classpath; Brotli support will be unavailable.
12:42:55.643 [default-nioEventLoopGroup-1-2] DEBUG i.n.handler.codec.compression.Zstd - zstd-jni not in the classpath; Zstd support will be unavailable.
12:42:55.646 [default-nioEventLoopGroup-1-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
12:42:55.646 [default-nioEventLoopGroup-1-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
12:42:55.646 [default-nioEventLoopGroup-1-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32
12:42:55.646 [default-nioEventLoopGroup-1-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.blocking: false
12:42:55.646 [default-nioEventLoopGroup-1-2] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.batchFastThreadLocalOnly: true
12:42:55.699 [default-nioEventLoopGroup-1-2] DEBUG i.m.s.t.reader.HttpHeaderTokenReader - Looking for bearer token in Authorization header
12:42:55.700 [default-nioEventLoopGroup-1-2] DEBUG i.m.s.t.reader.DefaultTokenResolver - Token <JWT_TOKEN> found in request GET /chat/mytopic/rjaros87
12:42:55.730 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: ServiceHttpClientConfiguration
12:42:55.730 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - No bean candidates found for type: ServiceHttpClientConfiguration
12:42:55.730 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: HttpClient
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - class io.micronaut.http.client.netty.DefaultHttpClient null Definition: io.micronaut.http.client.netty.DefaultNettyHttpClientRegistry
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [Definition: io.micronaut.http.client.netty.DefaultNettyHttpClientRegistry] for type: httpClient
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: DefaultNettyHttpClientRegistry
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - class io.micronaut.http.client.netty.DefaultNettyHttpClientRegistry null Definition: io.micronaut.http.client.netty.DefaultNettyHttpClientRegistry
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [Definition: io.micronaut.http.client.netty.DefaultNettyHttpClientRegistry] for type: defaultNettyHttpClientRegistry
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: ConversionService
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - class io.micronaut.context.env.DefaultEnvironment @Primary io.micronaut.context.DefaultRuntimeBeanDefinition@5149f008
12:42:55.731 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [io.micronaut.context.DefaultRuntimeBeanDefinition@5149f008] for type: conversionService
12:42:55.734 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: RequestBinderRegistry
12:42:55.734 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - class io.micronaut.http.bind.DefaultRequestBinderRegistry null Definition: io.micronaut.http.bind.DefaultRequestBinderRegistry
12:42:55.734 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - class io.micronaut.http.server.netty.binders.NettyServerRequestBinderRegistry null Definition: io.micronaut.http.server.netty.binders.NettyServerRequestBinderRegistry
12:42:55.734 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Searching for @Primary for type [requestBinderRegistry] from candidates: [Definition: io.micronaut.http.bind.DefaultRequestBinderRegistry, Definition: io.micronaut.http.server.netty.binders.NettyServerRequestBinderRegistry]
12:42:55.734 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Picked bean Definition: io.micronaut.http.bind.DefaultRequestBinderRegistry with the highest precedence for type RequestBinderRegistry and qualifier null
12:42:55.734 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [Definition: io.micronaut.http.bind.DefaultRequestBinderRegistry] for type: requestBinderRegistry
12:42:55.746 [default-nioEventLoopGroup-1-2] DEBUG io.netty.handler.ssl.OpenSsl - netty-tcnative not in the classpath; OpenSslEngine will be unavailable.
12:42:55.905 [default-nioEventLoopGroup-1-2] DEBUG io.netty.handler.ssl.JdkSslContext - Default protocols (JDK): [TLSv1.3, TLSv1.2]
12:42:55.905 [default-nioEventLoopGroup-1-2] DEBUG io.netty.handler.ssl.JdkSslContext - Default cipher suites (JDK): [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384]
12:42:55.912 [default-nioEventLoopGroup-1-2] DEBUG io.micronaut.context.lifecycle - Created bean [io.micronaut.http.client.netty.DefaultHttpClient@48118924] from definition [Definition: io.micronaut.http.client.netty.DefaultNettyHttpClientRegistry] with qualifier [null]
12:42:55.948 [io-executor-thread-1] DEBUG i.m.s.t.jwt.validator.JwtValidator - Validating signed JWT
12:42:55.949 [io-executor-thread-1] DEBUG i.m.s.t.jwt.validator.JwtValidator - JWT is signed and no signature configurations -> not verified
12:42:56.802 [default-nioEventLoopGroup-1-3] DEBUG io.netty.handler.ssl.SslHandler - [id: 0x952bb14c, L:/10.20.112.115:63237 - R:cognito-idp.us-east-1.amazonaws.com/35.175.54.203:443] HANDSHAKEN: protocol:TLSv1.3 cipher suite:TLS_AES_128_GCM_SHA256
12:42:57.017 [default-nioEventLoopGroup-1-3] DEBUG i.n.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@11707edc
12:42:57.046 [default-nioEventLoopGroup-1-3] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to https://cognito-idp.us-east-1.amazonaws.com/us-east-1_<COGNITO_ID>/.well-known/jwks.json
12:42:57.219 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Resolving beans for type: MediaTypeQualifier[type=MessageBodyReader<String>, mediaTypes=[application/json], annotationType=interface io.micronaut.http.annotation.Consumes] and Matches [MessageBodyReader<String>] io.micronaut.http.body.MessageBodyReader
12:42:57.219 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Found a registration BeanRegistration: io.micronaut.http.body.StringBodyReader@66434cc8 for candidate: Definition: io.micronaut.http.body.StringBodyReader with qualifier: MediaTypeQualifier[type=MessageBodyReader<String>, mediaTypes=[application/json], annotationType=interface io.micronaut.http.annotation.Consumes] and Matches [MessageBodyReader<String>]
12:42:57.227 [default-nioEventLoopGroup-1-3] DEBUG i.m.s.t.j.s.jwks.JwksSignatureUtils - JWT Key ID: XlSEdNJHs/GcbSFoU/9UFP8LNPNBDOFnbIYaaiteV20=
12:42:57.227 [default-nioEventLoopGroup-1-3] DEBUG i.m.s.t.j.s.jwks.JwksSignatureUtils - JWK Set Key IDs: fJQX50+mEwwgA0Offv7lYOT7xsTpiYzuwRu10zhasso=,XlSEdNJHs/GcbSFoU/9UFP8LNPNBDOFnbIYaaiteV20=
12:42:57.227 [default-nioEventLoopGroup-1-3] DEBUG i.m.s.t.j.s.jwks.JwksSignatureUtils - Found 1 matching JWKs
12:42:57.230 [default-nioEventLoopGroup-1-3] DEBUG i.m.s.t.j.n.ReactiveJwksSignature - JWT Signature verified: <JWT_TOKEN>
12:42:57.233 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: EmbeddedServer T
12:42:57.233 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - interface io.micronaut.http.server.netty.NettyEmbeddedServer null Definition: io.micronaut.http.server.netty.DefaultNettyEmbeddedServerFactory
12:42:57.233 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [Definition: io.micronaut.http.server.netty.DefaultNettyEmbeddedServerFactory] for type: T
12:42:57.234 [default-nioEventLoopGroup-1-3] DEBUG i.m.c.e.ApplicationEventPublisher - Publishing event: io.micronaut.security.event.TokenValidatedEvent[source=<JWT_TOKEN>]
12:42:57.234 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Resolving beans for type: <TokenValidatedEvent> io.micronaut.context.event.ApplicationEventListener
12:42:57.239 [default-nioEventLoopGroup-1-3] DEBUG i.m.security.filters.SecurityFilter - Attributes: sub=><AWS_CLIENT_ID>, token_use=>access, scope=>my/scope, auth_time=>1728636862, iss=>https://cognito-idp.us-east-1.amazonaws.com/us-east-1_BgKMT8cuh, exp=>Sat Oct 12 10:54:22 CEST 2024, iat=>Fri Oct 11 10:54:22 CEST 2024, version=>2, jti=>8e2e9524-8596-4974-a720-04dad089f535, client_id=><AWS_CLIENT_ID>
12:42:57.243 [default-nioEventLoopGroup-1-3] DEBUG i.m.security.rules.IpPatternsRule - One or more of the IP patterns matched the host address [0:0:0:0:0:0:0:1]. Continuing request processing.
12:42:57.245 [default-nioEventLoopGroup-1-3] DEBUG i.m.s.rules.AbstractSecurityRule - The given roles [[my/scope, isAnonymous(), isAuthenticated()]] matched one or more of the required roles [[isAuthenticated()]]. Allowing the request
12:42:57.245 [default-nioEventLoopGroup-1-3] DEBUG i.m.security.filters.SecurityFilter - Authorized request GET /chat/mytopic/rjaros87. The rule provider io.micronaut.security.rules.SecuredAnnotationRule authorized the request.
12:42:57.246 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: ChatServerWebSocket
12:42:57.246 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - class com.pega.example.ChatServerWebSocket null Definition: com.pega.example.ChatServerWebSocket
12:42:57.246 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [Definition: com.pega.example.ChatServerWebSocket] for type: chatServerWebSocket
12:42:57.246 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: ChatServerWebSocket
12:42:57.246 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - class com.pega.example.ChatServerWebSocket null Definition: com.pega.example.ChatServerWebSocket
12:42:57.246 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Qualifying bean [chatServerWebSocket] for qualifier: @ServerWebSocket
12:42:57.246 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [Definition: com.pega.example.ChatServerWebSocket] for type: @ServerWebSocket chatServerWebSocket
12:42:57.251 [default-nioEventLoopGroup-1-3] DEBUG i.n.h.c.h.w.WebSocketServerHandshaker - [id: 0x3fc4ca06, L:/[0:0:0:0:0:0:0:1]:8080 - R:/[0:0:0:0:0:0:0:1]:63236] WebSocket version V13 server handshake
12:42:57.251 [default-nioEventLoopGroup-1-3] DEBUG i.n.h.c.h.w.WebSocketServerHandshaker - WebSocket version 13 server handshake key: eeE3s7zsWlnpGrfVAS3eNw==, response: A7enmVIT1unUBwvxq1zJBf/oGUc=
12:42:57.259 [default-nioEventLoopGroup-1-2] ERROR i.m.h.s.netty.RoutingInBoundHandler - Micronaut Server Error - No request state present. Cause: class io.netty.handler.codec.http.websocketx.PingWebSocketFrame cannot be cast to class io.netty.handler.codec.http.HttpRequest (io.netty.handler.codec.http.websocketx.PingWebSocketFrame and io.netty.handler.codec.http.HttpRequest are in unnamed module of loader 'app')
java.lang.ClassCastException: class io.netty.handler.codec.http.websocketx.PingWebSocketFrame cannot be cast to class io.netty.handler.codec.http.HttpRequest (io.netty.handler.codec.http.websocketx.PingWebSocketFrame and io.netty.handler.codec.http.HttpRequest are in unnamed module of loader 'app')
at io.micronaut.http.server.netty.handler.PipeliningServerHandler$MessageInboundHandler.read(PipeliningServerHandler.java:371)
at io.micronaut.http.server.netty.handler.PipeliningServerHandler.channelRead(PipeliningServerHandler.java:221)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:289)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
12:42:57.267 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: ApplicationEventPublisher<WebSocketSessionOpenEvent T>
12:42:57.267 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - interface io.micronaut.context.event.ApplicationEventPublisher null io.micronaut.context.event.ApplicationEventPublisherFactory@77d28268
12:42:57.267 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [io.micronaut.context.event.ApplicationEventPublisherFactory@77d28268] for type: applicationEventPublisher
12:42:57.268 [default-nioEventLoopGroup-1-3] DEBUG io.micronaut.context.lifecycle - Created bean [io.micronaut.context.event.ApplicationEventPublisherFactory$2@5a4e830e] from definition [io.micronaut.context.event.ApplicationEventPublisherFactory@77d28268] with qualifier [null]
12:42:57.268 [default-nioEventLoopGroup-1-3] DEBUG i.m.c.e.ApplicationEventPublisher - Publishing event: io.micronaut.websocket.event.WebSocketSessionOpenEvent[source=WebSocket Session: eeE3s7zsWlnpGrfVAS3eNw==]
12:42:57.268 [default-nioEventLoopGroup-1-3] DEBUG i.m.context.DefaultBeanContext - Resolving beans for type: <WebSocketSessionOpenEvent> io.micronaut.context.event.ApplicationEventListener
12:42:59.261 [default-nioEventLoopGroup-1-2] DEBUG i.m.h.s.n.w.NettyServerWebSocketHandler - Closing WebSocket session WebSocket Session: eeE3s7zsWlnpGrfVAS3eNw== with reason CloseReason{code=1000, reason=''}
12:42:59.265 [default-nioEventLoopGroup-1-2] DEBUG i.m.h.s.n.w.NettyServerWebSocketHandler - Removing WebSocket Server session: WebSocket Session: eeE3s7zsWlnpGrfVAS3eNw==
12:42:59.265 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Finding candidate beans for type: ApplicationEventPublisher<WebSocketSessionClosedEvent T>
12:42:59.265 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - interface io.micronaut.context.event.ApplicationEventPublisher null io.micronaut.context.event.ApplicationEventPublisherFactory@77d28268
12:42:59.265 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Found concrete candidate [io.micronaut.context.event.ApplicationEventPublisherFactory@77d28268] for type: applicationEventPublisher
12:42:59.265 [default-nioEventLoopGroup-1-2] DEBUG io.micronaut.context.lifecycle - Created bean [io.micronaut.context.event.ApplicationEventPublisherFactory$2@4ed477ab] from definition [io.micronaut.context.event.ApplicationEventPublisherFactory@77d28268] with qualifier [null]
12:42:59.265 [default-nioEventLoopGroup-1-2] DEBUG i.m.c.e.ApplicationEventPublisher - Publishing event: io.micronaut.websocket.event.WebSocketSessionClosedEvent[source=WebSocket Session: eeE3s7zsWlnpGrfVAS3eNw==]
12:42:59.265 [default-nioEventLoopGroup-1-2] DEBUG i.m.context.DefaultBeanContext - Resolving beans for type: <WebSocketSessionClosedEvent> io.micronaut.context.event.ApplicationEventListener
12:43:57.214 [default-nioEventLoopGroup-1-3] DEBUG i.m.h.client.netty.DefaultHttpClient - Server sent GOAWAY frame. errorCode=0 base64(content)=
Without annotation or @Secured({SecurityRule.IS_ANONYMOUS}) it works correctly (without exception).
And temporary workaround is to wait >=10ms (tested on local machine), before sending any frames.
Execute below python script and verify Micronaut application logs
importasyncioimportwebsocketsWEBSOCKET_URL="ws://localhost:8080/chat/mytopic/rjaros87"JWT_TOKEN="<PROVIDE_VALID_JWT_TOKEN>"asyncdefon_open(websocket):
print("Connection opened")
# await asyncio.sleep(0.01) # Sleep for a short time to allow the server to process the connection (workaround)awaitwebsocket.ping()
print("Ping frame sent")
print("Going to close the connection in 2 seconds")
awaitasyncio.sleep(2)
awaitwebsocket.close()
asyncdefon_close(websocket):
print(f"Connection closed with code: {websocket.close_code}")
asyncdefconnect_and_ping():
headers= {
"Authorization": f"Bearer {JWT_TOKEN}"
}
asyncwithwebsockets.connect(WEBSOCKET_URL, extra_headers=headers) aswebsocket:
awaiton_open(websocket)
awaiton_close(websocket)
if__name__=="__main__":
asyncio.run(connect_and_ping())
Expected Behavior
Frames should be processed successfully without any exceptions being thrown.
Actual Behaviour
In current version of Micronaut (4.6.3) with enabled security and the
@Secured({SecurityRule.IS_AUTHENTICATED})
annotation is applied to a WebSocket server, a ClassCastException is thrown when any type of frame is sent after the onOpen event.WebSocket server preview:
the
ClassCastException
is thrown when any frame is sent after onOpen event. Here is a log output, e.g. from ping frame:Without annotation or
@Secured({SecurityRule.IS_ANONYMOUS})
it works correctly (without exception).And temporary workaround is to wait >=10ms (tested on local machine), before sending any frames.
Steps To Reproduce
@Secured({SecurityRule.IS_AUTHENTICATED})
annotationEnvironment Information
OS: MacOS, Linux, Docker
JDK: 17
Example Application
https://docs.micronaut.io/latest/guide/#websocketServer
Version
4.6.3
The text was updated successfully, but these errors were encountered: