django-websocket-redis icon indicating copy to clipboard operation
django-websocket-redis copied to clipboard

WebsocketWSGIServer.process_request jwt support

Open eagle21st opened this issue 11 years ago • 6 comments

Hi,

First of all, this is a great repo, thanks for the efforts!

Currently for each ws request, it goes through django session middleware for authentication, I tried to monkey patch this method in settings.py to parse JWT token and it worked with local runserver. However when running with uwsgi, this monkey patch is throwing an ImportError, I'm guessing it's causing circular import. My question is if it's possible to have native support of jwt authentication? Or maybe provide a way to inject custom function to replace the default process_request method?

eagle21st avatar Dec 19 '14 10:12 eagle21st

Currently for each ws request, it goes through django session middleware for authentication,

Yes, but the complete session data is fetched from Redis, so I don't see any big advantage in comparison with session data sent by the client. Or am I wrong on this assumption?

I read that Adrian Holovaty wrote on his blog, that he likes the idea of signed session data sent trough cookies, so whenever Django implements this, I'll jump on the train.

If you need this feature urgently, don't hesitate to contact me directly.

jrief avatar Dec 19 '14 10:12 jrief

@jrief Thanks for the reply

The way I implemented the authentication flow is through JWT, which doesn't require a session in redis or checking the Token table. The basic idea behind this is using a signed hash value that include the necessary user information inside of each HTTP request header, and backend would simply decode it and authenticate.

That's my normal django auth flow. Thus if I'd like to authenticate the same user that opened a ws connection, I'd need to follow the same steps here. That's the reason I feel the current process_request is not flexible enough to cover this case.

eagle21st avatar Dec 19 '14 19:12 eagle21st

@eagle21st I get your point and indeed ws4redis is not very flexible in this sense. Do you handle user authentication though a middleware class, such as django.contrib.auth.middleware.AuthenticationMiddleware?

Currently the user is set in WebsocketWSGIServer.process_request. Would it be possible to add your code to this function? If I have a running prototype using JWT, I could start to rewrite that function into something more flexible.

Could you please fork and try that.

jrief avatar Dec 19 '14 22:12 jrief

@jrief

Definitely, I'll try to fork and add my own logic. Mine doesn't have a middleware class for such authentication. I'm thinking define a callable func sort of like what you did with WS4REDIS_ALLOWED_CHANNELS, and inject into WebsocketWSGIServer.process_request

eagle21st avatar Dec 19 '14 23:12 eagle21st

From the point of view of a (good) Django developer, wouldn't it be better to implement it similar to django.contrib.auth.middleware.AuthenticationMiddleware? Having a well known and supported middleware class for authentication via JWT, would be a good incentive for me to add that to ws4redis.

jrief avatar Dec 19 '14 23:12 jrief

@jrief

Personally I like your suggestion. But one thing here is I'm using django rest framework, not sure it's a habit or something, they're defining AUTHENTICATION_CLASSES and call the process in each view to authenticate the request. Here's their docs(http://www.django-rest-framework.org/api-guide/authentication/) for authentication. I'm doing nothing but following this structure.

I assume defining a middleware class also works, haven't really find the balance here, so I decided to stick with their 'favored' syntax

eagle21st avatar Dec 19 '14 23:12 eagle21st