I'm trying to authenticate some of my STOMP topics using Spring Security:
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/webrtc/signal").hasRole("CLIENT")
.simpSubscribeDestMatchers("/signal/private").hasRole("CLIENT")
.simpSubscribeDestMatchers("/signal/public").permitAll();
}
This works as expected and devices can only connect if they have the right role. However, when a client tries to subscribe to a topic they don't have access to Spring throws the error Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
which then closes the STOMP connection on the client. Is there any way to gracefully deny the subscription without crashing and closing the connection?
If it helps, this is my authentication config:
@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);
assert accessor != null;
if (StompCommand.CONNECT.equals(accessor.getCommand()) && Objects.nonNull(accessor.getHeader("token"))) {
Authentication user =
jwtTokenProvider.getAuthentication((String) accessor.getHeader("token"));
accessor.setUser(user);
}
return message;
}
});
}