Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle CORS origins with Stomp and SockJS in Spring 5.3 and newer?

I'm working on a server application which uses both REST endpoints and a SockJS websocket. This used to work fine under Spring 5.2 and below.

However, since the 5.3 release, the following method exists within org.springframework.web.cors.CorsConfiguration:

    public void validateAllowCredentials() {
        if (this.allowCredentials == Boolean.TRUE &&
                this.allowedOrigins != null && this.allowedOrigins.contains(ALL)) {

            throw new IllegalArgumentException(
                    "When allowCredentials is true, allowedOrigins cannot contain the special value \"*\"" +
                            "since that cannot be set on the \"Access-Control-Allow-Origin\" response header. " +
                            "To allow credentials to a set of origins, list them explicitly " +
                            "or consider using \"allowedOriginPatterns\" instead.");
        }
    }

So far, my socket was configured like this:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // prefix for the client to send messages to the server
        config.setApplicationDestinationPrefixes("/app");
        // prefix for the client to receive broadcasted messages from the server
        config.enableSimpleBroker("/topic");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // defines the url of the socket so the client can connect to it
        registry.addEndpoint("/socketendpoint").setAllowedOrigins("*").withSockJS();
    }
} 

Now I'm facing a real issue:

  • If I keep the setAllowedOrigins("*") in the WebSocketConfiguration, then I will face the error thrown in validateAllowCredentials.
  • If I remove the setAllowedOrigins("*"), then the SockJS clients will recieve an Error during WebSocket handshake: Unexpected response code: 403.

I don't know the origin domain at compile time.

I already tried a Cors Filter and a Cors Configuration that use the typical "return the origin header you find in the request as allow-origin" pattern that is usually used to circumvent the allow-origin: "*", but some SockJS requests don't have an origin header assigned...

How do I fix this?

like image 565
Alan47 Avatar asked Dec 03 '20 15:12

Alan47


People also ask

How do you add CORS to origin in spring boot?

Enable CORS in Controller Method We need to set the origins for RESTful web service by using @CrossOrigin annotation for the controller method. This @CrossOrigin annotation supports specific REST API, and not for the entire application.

What is SockJS and stomp?

The WebSocket API enables web applications to handle bidirectional communications whereas STOMP is a simple text-orientated messaging protocol. A Bidirectional WebSocket allows a web server to initiate a new message to a client, rather than wait for the client to request updates.

Is Cors enabled by default in spring boot?

No. You need to add @CrossOrigin annotation by yourself to get CORS Support in Spring. Why: Enabling CORS (Cross-origin resource sharing) by default will be a serious security issue.

What is spring WebSocket and Stomp?

Spring WebSocket is the Spring module that enables WebSocket-style messaging support. As Spring WebSocket’s documentation states, the WebSocket protocol defines an important new capability for web applications: full-duplex, two-way communication between client and server. Well, now that we know what WebSocket, STOMP, SockJS and Spring WebSocket.

What is the use of sockjs in spring?

If that fails it can use a variety of browser-specific transport protocols and presents them through WebSocket-like abstractions. SockJS is used to enable fallback options for browsers that don’t support WebSocket. Spring provides a server-side implementation of SockJS and we will see how to use the same in this example.

What is Cors in spring and how does it work?

In such a case, CORS enables cross-domain communication. Spring provides first-class support for CORS, offering an easy and powerful way of configuring it in any Spring or Spring Boot web application. A quick and practical guide to working with CORS and Spring Webflux.

What are the sockjs rules for origin requests?

Each provided allowed origin must start by "http://", "https://" or be "*" (means that all origins are allowed). By default, only same origin requests are allowed (empty list). Since: 4.1.2 See Also: RFC 6454: The Web Origin Concept , SockJS supported transports by browser


2 Answers

For future reference, with the latest spring updates, there's now a method setAllowedOriginPatterns that solves this:

 registry.addEndpoint("/socketendpoint").setAllowedOriginPatterns("*").withSockJS();
like image 148
Alan47 Avatar answered Nov 15 '22 00:11

Alan47


From the documentation

Configure allowed Origin header values. This check is mostly designed for browser clients. There is nothing preventing other types of client to modify the Origin header value. When SockJS is enabled and origins are restricted, transport types that do not allow to check request origin (Iframe based transports) are disabled. As a consequence, IE 6 to 9 are not supported when origins are restricted. Each provided allowed origin must start by "http://", "https://" or be "*" (means that all origins are allowed). By default, only same origin requests are allowed (empty list). Since: 4.1.2 See Also: RFC 6454: The Web Origin Concept , SockJS supported transports by browser

Your code

registry.addEndpoint("/socketendpoint").setAllowedOrigins("*").setAllowedOrigins().withSockJS();

Should be

 registry.addEndpoint("/socketendpoint").setAllowedOrigins("*").withSockJS();
like image 44
Dirk Deyne Avatar answered Nov 15 '22 00:11

Dirk Deyne