Spring WebSocket Stomp Exception Handling









up vote
0
down vote

favorite












I am trying to use Websockets and STOMP 1.2. I want to authenticate user using JWT on CONNECT frame and to return error message if authorization is not valid. Here is channel interceptor



@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer

// ... Removed for readability

@Override
public void configureClientInboundChannel(ChannelRegistration registration)

registration.interceptors(new ChannelInterceptor()

@Override
public Message<?> preSend(Message<?> message, MessageChannel channel)

StompHeaderAccessor accessor =
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand()))

String token = accessor.getFirstNativeHeader(authorizationHeader);
if (token != null)

Authentication authentication = tokenUtil.getAuthentication(resolveToken(token));
accessor.setUser(authentication);

else

throw new UnauthorizedException();


return message;

);





This way the error stack will have



 Failed to send client message to application via MessageChannel in session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f. Sending STOMP ERROR to client.

org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:284) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:324) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
Caused by: com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
at com.exampleconfig.WebSocketConfig$1.preSend(WebSocketConfig.java:74) ~[classes/:na]
at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
... 28 common frames omitted


And similar error will be sent to client end connection will be closed.
But after the connection is closed, other stack trace is written as output:



2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] s.w.s.h.LoggingWebSocketHandlerDecorator : StandardWebSocketSession[id=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f, uri=/api/ws] closed with CloseStatus[code=1000, reason=null]
2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] o.s.w.s.m.SubProtocolWebSocketHandler : Clearing session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
2018-11-11 01:06:48.084 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Detected unsent DISCONNECT message. Processing anyway.
2018-11-11 01:06:48.085 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Processing DISCONNECT session=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
2018-11-11 01:06:48.086 DEBUG 7259 --- [tboundChannel-1] o.s.w.s.m.SubProtocolWebSocketHandler : No session for GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT_ACK, simpDisconnectMessage=GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes=org.springframework.messaging.simp.SimpAttributes.COMPLETED=true, simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f], simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f]
2018-11-11 01:06:48.087 WARN 7259 --- [nio-8080-exec-2] w.s.h.ExceptionWebSocketHandlerDecorator : Unhandled exception after connection closed for ExceptionWebSocketHandlerDecorator [delegate=LoggingWebSocketHandlerDecorator [delegate=SubProtocolWebSocketHandler[StompSubProtocolHandler[v10.stomp, v11.stomp, v12.stomp]]]]

org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.messaging.StompSubProtocolHandler.afterSessionEnded(StompSubProtocolHandler.java:611) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.clearSession(SubProtocolWebSocketHandler.java:516) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.afterConnectionClosed(SubProtocolWebSocketHandler.java:385) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:144) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.WsSession.onClose(WsSession.java:513) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:347) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:289) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:69) ~[spring-security-messaging-5.1.1.RELEASE.jar:5.1.1.RELEASE]
at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
... 26 common frames omitted


I have no idea where AccessDeniedException came from and how can I handle this.



If I do not throw UnauthorizedException in preSend method, client will be connected and when it tries to send something, it will receive AccessDeniedException, because all endpoints needs authenticated user, and then connection will be closed and stack trace for AccessDeniedException printed few times.



What am I doing incorrect here and what is the correct way to handle this kind of use case?










share|improve this question

























    up vote
    0
    down vote

    favorite












    I am trying to use Websockets and STOMP 1.2. I want to authenticate user using JWT on CONNECT frame and to return error message if authorization is not valid. Here is channel interceptor



    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer

    // ... Removed for readability

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration)

    registration.interceptors(new ChannelInterceptor()

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel)

    StompHeaderAccessor accessor =
    MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

    if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand()))

    String token = accessor.getFirstNativeHeader(authorizationHeader);
    if (token != null)

    Authentication authentication = tokenUtil.getAuthentication(resolveToken(token));
    accessor.setUser(authentication);

    else

    throw new UnauthorizedException();


    return message;

    );





    This way the error stack will have



     Failed to send client message to application via MessageChannel in session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f. Sending STOMP ERROR to client.

    org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:284) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:324) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
    Caused by: com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
    at com.exampleconfig.WebSocketConfig$1.preSend(WebSocketConfig.java:74) ~[classes/:na]
    at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    ... 28 common frames omitted


    And similar error will be sent to client end connection will be closed.
    But after the connection is closed, other stack trace is written as output:



    2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] s.w.s.h.LoggingWebSocketHandlerDecorator : StandardWebSocketSession[id=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f, uri=/api/ws] closed with CloseStatus[code=1000, reason=null]
    2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] o.s.w.s.m.SubProtocolWebSocketHandler : Clearing session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
    2018-11-11 01:06:48.084 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Detected unsent DISCONNECT message. Processing anyway.
    2018-11-11 01:06:48.085 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Processing DISCONNECT session=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
    2018-11-11 01:06:48.086 DEBUG 7259 --- [tboundChannel-1] o.s.w.s.m.SubProtocolWebSocketHandler : No session for GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT_ACK, simpDisconnectMessage=GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes=org.springframework.messaging.simp.SimpAttributes.COMPLETED=true, simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f], simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f]
    2018-11-11 01:06:48.087 WARN 7259 --- [nio-8080-exec-2] w.s.h.ExceptionWebSocketHandlerDecorator : Unhandled exception after connection closed for ExceptionWebSocketHandlerDecorator [delegate=LoggingWebSocketHandlerDecorator [delegate=SubProtocolWebSocketHandler[StompSubProtocolHandler[v10.stomp, v11.stomp, v12.stomp]]]]

    org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.messaging.StompSubProtocolHandler.afterSessionEnded(StompSubProtocolHandler.java:611) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.clearSession(SubProtocolWebSocketHandler.java:516) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.afterConnectionClosed(SubProtocolWebSocketHandler.java:385) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:144) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.WsSession.onClose(WsSession.java:513) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:347) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:289) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
    at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
    Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:69) ~[spring-security-messaging-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    ... 26 common frames omitted


    I have no idea where AccessDeniedException came from and how can I handle this.



    If I do not throw UnauthorizedException in preSend method, client will be connected and when it tries to send something, it will receive AccessDeniedException, because all endpoints needs authenticated user, and then connection will be closed and stack trace for AccessDeniedException printed few times.



    What am I doing incorrect here and what is the correct way to handle this kind of use case?










    share|improve this question























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I am trying to use Websockets and STOMP 1.2. I want to authenticate user using JWT on CONNECT frame and to return error message if authorization is not valid. Here is channel interceptor



      @Configuration
      @EnableWebSocketMessageBroker
      public class WebSocketConfig implements WebSocketMessageBrokerConfigurer

      // ... Removed for readability

      @Override
      public void configureClientInboundChannel(ChannelRegistration registration)

      registration.interceptors(new ChannelInterceptor()

      @Override
      public Message<?> preSend(Message<?> message, MessageChannel channel)

      StompHeaderAccessor accessor =
      MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

      if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand()))

      String token = accessor.getFirstNativeHeader(authorizationHeader);
      if (token != null)

      Authentication authentication = tokenUtil.getAuthentication(resolveToken(token));
      accessor.setUser(authentication);

      else

      throw new UnauthorizedException();


      return message;

      );





      This way the error stack will have



       Failed to send client message to application via MessageChannel in session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f. Sending STOMP ERROR to client.

      org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:284) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:324) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
      Caused by: com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
      at com.exampleconfig.WebSocketConfig$1.preSend(WebSocketConfig.java:74) ~[classes/:na]
      at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      ... 28 common frames omitted


      And similar error will be sent to client end connection will be closed.
      But after the connection is closed, other stack trace is written as output:



      2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] s.w.s.h.LoggingWebSocketHandlerDecorator : StandardWebSocketSession[id=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f, uri=/api/ws] closed with CloseStatus[code=1000, reason=null]
      2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] o.s.w.s.m.SubProtocolWebSocketHandler : Clearing session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
      2018-11-11 01:06:48.084 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Detected unsent DISCONNECT message. Processing anyway.
      2018-11-11 01:06:48.085 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Processing DISCONNECT session=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
      2018-11-11 01:06:48.086 DEBUG 7259 --- [tboundChannel-1] o.s.w.s.m.SubProtocolWebSocketHandler : No session for GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT_ACK, simpDisconnectMessage=GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes=org.springframework.messaging.simp.SimpAttributes.COMPLETED=true, simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f], simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f]
      2018-11-11 01:06:48.087 WARN 7259 --- [nio-8080-exec-2] w.s.h.ExceptionWebSocketHandlerDecorator : Unhandled exception after connection closed for ExceptionWebSocketHandlerDecorator [delegate=LoggingWebSocketHandlerDecorator [delegate=SubProtocolWebSocketHandler[StompSubProtocolHandler[v10.stomp, v11.stomp, v12.stomp]]]]

      org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.StompSubProtocolHandler.afterSessionEnded(StompSubProtocolHandler.java:611) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.clearSession(SubProtocolWebSocketHandler.java:516) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.afterConnectionClosed(SubProtocolWebSocketHandler.java:385) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:144) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsSession.onClose(WsSession.java:513) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:347) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:289) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
      Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
      at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
      at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:69) ~[spring-security-messaging-5.1.1.RELEASE.jar:5.1.1.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      ... 26 common frames omitted


      I have no idea where AccessDeniedException came from and how can I handle this.



      If I do not throw UnauthorizedException in preSend method, client will be connected and when it tries to send something, it will receive AccessDeniedException, because all endpoints needs authenticated user, and then connection will be closed and stack trace for AccessDeniedException printed few times.



      What am I doing incorrect here and what is the correct way to handle this kind of use case?










      share|improve this question













      I am trying to use Websockets and STOMP 1.2. I want to authenticate user using JWT on CONNECT frame and to return error message if authorization is not valid. Here is channel interceptor



      @Configuration
      @EnableWebSocketMessageBroker
      public class WebSocketConfig implements WebSocketMessageBrokerConfigurer

      // ... Removed for readability

      @Override
      public void configureClientInboundChannel(ChannelRegistration registration)

      registration.interceptors(new ChannelInterceptor()

      @Override
      public Message<?> preSend(Message<?> message, MessageChannel channel)

      StompHeaderAccessor accessor =
      MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

      if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand()))

      String token = accessor.getFirstNativeHeader(authorizationHeader);
      if (token != null)

      Authentication authentication = tokenUtil.getAuthentication(resolveToken(token));
      accessor.setUser(authentication);

      else

      throw new UnauthorizedException();


      return message;

      );





      This way the error stack will have



       Failed to send client message to application via MessageChannel in session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f. Sending STOMP ERROR to client.

      org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:284) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:324) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
      Caused by: com.example.error.exception.UnauthorizedException: You are not authorized. Please log in.
      at com.exampleconfig.WebSocketConfig$1.preSend(WebSocketConfig.java:74) ~[classes/:na]
      at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      ... 28 common frames omitted


      And similar error will be sent to client end connection will be closed.
      But after the connection is closed, other stack trace is written as output:



      2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] s.w.s.h.LoggingWebSocketHandlerDecorator : StandardWebSocketSession[id=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f, uri=/api/ws] closed with CloseStatus[code=1000, reason=null]
      2018-11-11 01:06:48.077 DEBUG 7259 --- [nio-8080-exec-2] o.s.w.s.m.SubProtocolWebSocketHandler : Clearing session a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
      2018-11-11 01:06:48.084 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Detected unsent DISCONNECT message. Processing anyway.
      2018-11-11 01:06:48.085 DEBUG 7259 --- [nio-8080-exec-2] org.springframework.web.SimpLogging : Processing DISCONNECT session=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f
      2018-11-11 01:06:48.086 DEBUG 7259 --- [tboundChannel-1] o.s.w.s.m.SubProtocolWebSocketHandler : No session for GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT_ACK, simpDisconnectMessage=GenericMessage [payload=byte[0], headers=simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes=org.springframework.messaging.simp.SimpAttributes.COMPLETED=true, simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f], simpSessionId=a63cf95f-4a5b-ef34-b74b-3264ec6dd61f]
      2018-11-11 01:06:48.087 WARN 7259 --- [nio-8080-exec-2] w.s.h.ExceptionWebSocketHandlerDecorator : Unhandled exception after connection closed for ExceptionWebSocketHandlerDecorator [delegate=LoggingWebSocketHandlerDecorator [delegate=SubProtocolWebSocketHandler[StompSubProtocolHandler[v10.stomp, v11.stomp, v12.stomp]]]]

      org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.StompSubProtocolHandler.afterSessionEnded(StompSubProtocolHandler.java:611) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.clearSession(SubProtocolWebSocketHandler.java:516) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.afterConnectionClosed(SubProtocolWebSocketHandler.java:385) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.WebSocketHandlerDecorator.afterConnectionClosed(WebSocketHandlerDecorator.java:85) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.afterConnectionClosed(LoggingWebSocketHandlerDecorator.java:72) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.afterConnectionClosed(ExceptionWebSocketHandlerDecorator.java:78) ~[spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onClose(StandardWebSocketHandlerAdapter.java:144) [spring-websocket-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:535) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsSession.onClose(WsSession.java:513) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:347) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:289) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-9.0.12.jar:9.0.12]
      at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12]
      at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
      Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
      at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE]
      at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:69) ~[spring-security-messaging-5.1.1.RELEASE.jar:5.1.1.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132) ~[spring-messaging-5.1.2.RELEASE.jar:5.1.2.RELEASE]
      ... 26 common frames omitted


      I have no idea where AccessDeniedException came from and how can I handle this.



      If I do not throw UnauthorizedException in preSend method, client will be connected and when it tries to send something, it will receive AccessDeniedException, because all endpoints needs authenticated user, and then connection will be closed and stack trace for AccessDeniedException printed few times.



      What am I doing incorrect here and what is the correct way to handle this kind of use case?







      spring spring-security spring-websocket stomp






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 11 at 0:21









      Boris

      6510




      6510



























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244720%2fspring-websocket-stomp-exception-handling%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes















           

          draft saved


          draft discarded















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244720%2fspring-websocket-stomp-exception-handling%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Barbados

          How to read a connectionString WITH PROVIDER in .NET Core?

          Node.js Script on GitHub Pages or Amazon S3