I want to secure websockets in spring boot. So far i've sucesfully managed to secure normal http requests, but having issues with websockets. I want to be able to secure and then, also, send messages to specific users. According to those sources:
- https://docs.spring.io/spring/docs/4.3.12.RELEASE/spring-framework-reference/html/new-in-4.2.html
- JSON Web Token (JWT) with Spring based SockJS / STOMP Web Socket
i've wrote this code:
@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
@Slf4j
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Autowired
private JwtTokenProvider jwtTokenProvider;
@Autowired
private CustomUserServiceDetails customUserServiceDetails;
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/voting-socket").setAllowedOrigins("*").withSockJS();
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new ChannelInterceptorAdapter() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String header = accessor.getFirstNativeHeader("Authorization");
log.info("Header auth token: " + header);
String jwt = JwtTokenProvider.getToken(header);
log.info("Token only : " + jwt);
if (StringUtils.hasText(jwt) && jwtTokenProvider.validateToken(jwt)) {
Long userId = jwtTokenProvider.getUserIdFromJWT(jwt);
User user = (User) customUserServiceDetails.loadUserById(userId);
Principal principal = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
if (Objects.isNull(principal))
return null;
accessor.setUser(principal);
} else if (StompCommand.DISCONNECT.equals(accessor.getCommand())) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (Objects.nonNull(authentication))
log.info("Disconnected Auth : " + authentication.getName());
else
log.info("Disconnected Sess : " + accessor.getSessionId());
}
}
return message;
}
});
}
}
and this works as expected (authentication works). However now when i want to add user registry:
@Autowired
private SimpUserRegistry userRegistry;
my code is not executed at all (but not getting any error about wiring or anything). What am i doing wrong here? Or maybe i should use some diff approach. Once again my main goals are:
- authentication
- ability to use converAndSendToUser method.