Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCastException triggered when sending WebSocket frame with Secured annotation after onOpen event #11252

Open
rjaros87 opened this issue Oct 11, 2024 · 0 comments
Labels
type: bug Something isn't working

Comments

@rjaros87
Copy link

rjaros87 commented Oct 11, 2024

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:

@Secured({SecurityRule.IS_AUTHENTICATED}) //<--- triggers ClassCastException for any frame send just after onOpen event (client side)
@ServerWebSocket("/chat/{topic}/{username}") // (1)
public class ChatServerWebSocket {
// 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.

Steps To Reproduce

  1. Create Micronaut application based on Micronaut Guide
  2. Enable security (in my case I used AWS Cognito, here is Micronaut Guide for that)
  3. Add @Secured({SecurityRule.IS_AUTHENTICATED}) annotation
  4. Start application
  5. Execute below python script and verify Micronaut application logs
import asyncio
import websockets

WEBSOCKET_URL = "ws://localhost:8080/chat/mytopic/rjaros87"
JWT_TOKEN = "<PROVIDE_VALID_JWT_TOKEN>"

async def on_open(websocket):
    print("Connection opened")
    # await asyncio.sleep(0.01) # Sleep for a short time to allow the server to process the connection (workaround)
    await websocket.ping()
    print("Ping frame sent")

    print("Going to close the connection in 2 seconds")
    await asyncio.sleep(2)
    await websocket.close()

async def on_close(websocket):
    print(f"Connection closed with code: {websocket.close_code}")

async def connect_and_ping():
    headers = {
        "Authorization": f"Bearer {JWT_TOKEN}"
    }
    async with websockets.connect(WEBSOCKET_URL, extra_headers=headers) as websocket:
        await on_open(websocket)

        await on_close(websocket)

if __name__ == "__main__":
    asyncio.run(connect_and_ping())

Environment Information

OS: MacOS, Linux, Docker
JDK: 17

Example Application

https://docs.micronaut.io/latest/guide/#websocketServer

Version

4.6.3

@yawkat yawkat added the type: bug Something isn't working label Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants