1

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:

enter image description here

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.

Rasool Ghafari
  • 4,128
  • 7
  • 44
  • 71

0 Answers0