Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

400 WebSocket connection denied: origin 'file://' not allowed #392

Closed
FahadAlbukhari opened this issue Oct 10, 2016 · 9 comments
Closed

Comments

@FahadAlbukhari
Copy link

FahadAlbukhari commented Oct 10, 2016

400 WebSocket connection denied: origin 'file://' not allowed
that whah I got from ngrok when I am connect ionic android with my Django App through WebSocket django/channels

"Alright, the problem was somehow related to the origin header. Ionic seems to be sending a origin header containing "file://..", which was getting rejected / blocked by the websocket server." (platzhersh, http://stackoverflow.com/a/39552561)

I used
https://github.com/joewalnes/reconnecting-websocket
and
https://github.com/AngularClass/angular-websocket

same result 400 WebSocket connection denied: origin 'file://' not allowed

@andrewgodwin
Copy link
Member

It looks like either the browser or our WebSocket library is rejecting your connection because it's cross-domain - for security reasons connections out from a HTML page under file:// to external resources aren't allowed. I suggest you use runserver and view the page as a http://localhost/abc/def URL instead and it will then allow the connection.

@FahadAlbukhari
Copy link
Author

FahadAlbukhari commented Oct 10, 2016

It is working on android & ios emulator not on the device.
Does that mean I can not use WebSocket django/channels library with Ionic Framework android and IOS expect if the app at the same server?

@andrewgodwin
Copy link
Member

If you're using WebSockets natively you should be able to set the Origin header that you're sending (having it be file:// seems like a bad default) - you want to match the hostname. If not, there's potential we can override the autobahn security check but that would open your site up to cross-site attacks from browsers potentially.

@davidmarquis
Copy link
Contributor

davidmarquis commented Jan 29, 2017

This turns out to be a real issue with PhoneGap/Cordova apps... when running such an app on Android - and that may be the case with iOS and their MKWebView as well - the browser systematically sends file:// as the value for the Origin header (because the app runs in a web view, with all files served from the local filesystem).

I believe there's no way to control the value of that header which makes this a show stopper unless we have a mean of allowing file:// as an allowed origin on the server side.

Would there be a way to pass configuration options for the underlying Autobahn WebSocket factory via Daphne? More specifically, the allowedOrigins protocol option.

@andrewgodwin
Copy link
Member

There isn't a way, mostly because we leave allowedOrigins as the default of * and let the application decide if it wants to accept things in the connect handler. Do you know if * is not good enough to match file:///?

@davidmarquis
Copy link
Contributor

Weirdly enough, it doesn't look like * makes it as the Daphne server returns this status code when the browser initiates the WS connection:

400 WebSocket connection denied: origin 'file://' not allowed

I had a quick look at Autobahn's code and it appears the check for matching the Origin header against the allowedOriginPatterns is here.

The allowedOrigin configuration is transformed to a list of allowedOriginPatterns here.

The above would mean an allowedOrigin configuration of ['*'] would be transformed to the following list of regex pattern: ['^.*$'], which should theoretically work...

A closer look at the code leads me to believe the following line is suspicious in Autobahn's _is_same_origin function:

if not isinstance(websocket_origin, tuple) or not len(websocket_origin) == 3:
        raise ValueError("'websocket_origin' must be a 3-tuple")

It is possible that if the code upstream does not properly parse the file:// origin as a 3 elements tuple, then an exception would be thrown... I'll need to dive a little deeper into this... I'll keep you posted.

@davidmarquis
Copy link
Contributor

OK the culprit is right here:

 if websocket_origin == 'null':
        # nothing is the same as the null origin
        return False

websocket_origin does have a value of 'null' when the Origin header is set to file://.

Looking at the code that checks whether the origin header is allowed or not, it appears a plausible solution would be to configure the protocol option allowNullOrigin to True:

if have_origin:
    if origin_tuple == 'null' and self.factory.allowNullOrigin:
        origin_is_allowed = True
    else:
    ...

@andrewgodwin thoughts? It appears this is more an issue with Daphne than Channels but it somewhat touches on Channels as it wraps Daphne at least when bootstrapping the local development server with the runserver management command... :/

@davidmarquis
Copy link
Contributor

BTW I'll be happy to help on improving this, I just think I need some guidance on the best way to approach this considering both Channels and Daphne.

@andrewgodwin
Copy link
Member

Yes, this would definitely be an issue to open/patch in Daphne instead. I'd say for now it's acceptable to just set allowNullOrigin to be true as long as the Origin header makes it through in websocket.connect's headers key, so the app can choose what to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants