Starscream icon indicating copy to clipboard operation
Starscream copied to clipboard

"Origin" header has to be set

Open AndrewX192 opened this issue 5 years ago • 9 comments

Previous versions of Starscream (pre 3.0.0) allowed the Origin to be left unset by setting socket.origin = nil, whereas in newer versions will set the Origin header automatically if it wasn't set on the request.

Is there any chance we have this original behavior restored?

AndrewX192 avatar Sep 22 '19 01:09 AndrewX192

Hi @AndrewX192 could you help with PR? Thanks!

fassko avatar Oct 01 '19 19:10 fassko

@AndrewX192 is there a reason you don't want the Origin header set? It is a fairly common header to include. Does setting the origin to an empty string resolve the issue? Also 4.0.0 was released which I was suggest upgrading to (but it still contains the origin setting logic if it isn't included).

daltoniam avatar Jan 03 '20 20:01 daltoniam

Hi @daltoniam, sorry I haven't had cycles to look at this in more detail. The problem I'm having is that different backends and clients have different understandings of how the Origin header should be utilized. Generally, web browsers are good about setting the Origin header on HTTP requests other than an HTTP GET, but use cases outside of browsers are less predictable (as has been the behavior of Starscream thus far).

In my specific case, a server accepts requests from both a web browser, and a mobile (iOS app). When a user utilizes a websocket from their browser the origin is correct (app.example.com) connects to client.app.example.com, however in a mobile context there's no root origin, so the origin becomes the same as the hostname we are connecting to (client.app.example.com). Since this wasn't expected, it wasn't on the Origin whitelist and caused requests to fail, however removing the Origin header means that the server recognizes this is a non-browser use-case and the request is permitted.

Realistically, this is not a big problem for me - I'm happy to continue whitelisting the secnd origin, but as someone who went through the effort of updating Starscream in my application, I figured I'd raise this in the event someone else will run into this issue. If you feel that it's not a significant enough issue, then I'm happy to see this resolved as-is if you're comfortable with the current behavior. As far as I'm aware, there's no specific direction from RFCs in regards to when to set the Origin header beyond "The user agent MAY include an Origin header field in any HTTP request".

AndrewX192 avatar Jan 15 '20 09:01 AndrewX192

I'm currently engaging a bug witch caused by Starscream and golang websocket library Gorilla.

Starscream set Origin to upgrade request header with a port even it is default 80 or 443 just if the port is written into socket initial method's URL parameter, like "wss://example.com:443", then the origin header is set to "wss://example.com:443" too.

Gorilla initialize a websocket server with a default origin checker method "checkSameOrigin":

func checkSameOrigin(r *http.Request) bool {
	origin := r.Header["Origin"]
	if len(origin) == 0 {
		return true
	}
	u, err := url.Parse(origin[0])
	if err != nil {
		return false
	}
	return equalASCIIFold(u.Host, r.Host)
}

Here is Golang's URL structure from net/url package:

type URL struct {
    Scheme     string
    Opaque     string    // encoded opaque data
    User       *Userinfo // username and password information
    Host       string    // host or host:port
    Path       string    // path (relative paths may omit leading slash)
    RawPath    string    // encoded path hint (see EscapedPath method); added in Go 1.5
    ForceQuery bool      // append a query ('?') even if RawQuery is empty; added in Go 1.7
    RawQuery   string    // encoded query values, without '?'
    Fragment   string    // fragment for references, without '#'
}

You can see the Host cloud be host:port format, so compare between request's host and origin's host will fail.

That's what @AndrewX192 was talking about, neither Starscream or Gorilla goes wrong, but it is a problem indeed.

rcio avatar Mar 04 '20 05:03 rcio

I use the lib to connect to LG TV, It returns error "invalid origin" with code 1008. When I remove these lines:

 if request.value(forHTTPHeaderField: HTTPWSHeader.originName) == nil {
            var origin = url.absoluteString
            if let hostUrl = URL (string: "/", relativeTo: url) {
                origin = hostUrl.absoluteString
                origin.remove(at: origin.index(before: origin.endIndex))
            }
            req.setValue(origin, forHTTPHeaderField: HTTPWSHeader.originName)
 }

It works fine. So It's better if we can set it as optional, should not must to set

anlam87 avatar May 05 '20 03:05 anlam87

I have the same problem as anlam87, would be great if you did it optionally

b-huebner avatar Jun 24 '20 19:06 b-huebner

I also have the same problem as @anlam87 and @benjaminhuebner . Also trying to connect to an LG Smart TV. Did you guys find a solution to connect to the TV?

georgbachmann avatar Apr 08 '22 10:04 georgbachmann

+1. Unexpected origin header can cause very subtle issues. For my case, some server checks for reachability to Origin address only if it exists. If library inserts Origin implicitly, it's very difficult to find out why it fails and doesn't work. We were very lucky as the server was under our control so we could check the logs, but if we need to deal with external servers, it will be very very very difficult to figure out what the problem is.

hoon-prestolabs avatar Jul 04 '22 09:07 hoon-prestolabs

Also, it's not easy to "define" origin address for mobile apps. Unlike websites which browsers tracks proper origin values, apps do not have such origin address and just have endpoint. Websocket endpoint addresses with deleted path component are not guaranteed to work and server can refuse service.

hoon-prestolabs avatar Jul 04 '22 10:07 hoon-prestolabs