I configured socket in my spring boot + angularjs application and you can see configuration classes here:
WebSocketBrokerConfig
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/looping")
.withSockJS()
.setClientLibraryUrl("https://cdn.jsdelivr.net/sockjs/1.1.2/sockjs.min.js");
}
}
WebSocketSecurityConfig
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages.anyMessage().authenticated();
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
WebSocketAuthenticationConfig
@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketAuthenticationConfig implements WebSocketMessageBrokerConfigurer {
private static final Logger logger = LoggerFactory.getLogger(WebSocketAuthenticationConfig.class);
@Autowired
private TokenProvider tokenProvider;
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Autowired
private IUserService iUserService;
@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 (StompCommand.CONNECT.equals(accessor.getCommand())) {
String jwt = getJwtFromRequest(accessor);
logger.debug("X-Authorization: {}", jwt);
Long userId = tokenProvider.getUserIdFromToken(jwt);
User user = iUserService.loadById(userId);
UserDetails userDetails = customUserDetailsService.loadUserById(userId);
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, authorities);
accessor.setUser(authentication);
}
return message;
}
});
}
private String getJwtFromRequest(StompHeaderAccessor accessor) {
String bearerToken = accessor.getFirstNativeHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
and this is client side:
function SocketController($timeout, localStorageService) {
var vm = this;
var accessToken = localStorageService.get('accessToken');
var stompClient;
console.log(accessToken)
if (accessToken) {
stompClient = webstomp.over(new WebSocket('ws://localhost:8000/looping'));
stompClient.connect({"Authorization": "Bearer " + accessToken}, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/loops', function (message) {
console.log(message);
});
});
} else {
console.log("token expired");
}
}
In this case i see this below error in firefox devtools:
I also tried with SockJS as you can see below:
function SocketController($timeout, localStorageService) {
var vm = this;
var accessToken = localStorageService.get('accessToken');
var stompClient;
console.log(accessToken)
if (accessToken) {
var socket = new SockJS('https://localhost:8000/looping');
stompClient = Stomp.over(socket);
stompClient.connect({"Authorization": "Bearer " + accessToken}, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/loops', function (message) {
console.log(message);
});
});
} else {
console.log("token expired");
}
}
And with SockJS
i get 401 error when var socket = new SockJS('https://localhost:8000/looping');
is called.
NOTE
I using token oauth2 authorization and need to send token when handshaking for socket.