jrief / django-websocket-redis

Websockets for Django applications using Redis as message queue
http://django-websocket-redis.awesto.com/
MIT License
896 stars 222 forks source link

Using Token Auth for my app instead of Sessions #164

Open domface opened 8 years ago

domface commented 8 years ago

Hi,

If I am using token auth in my app instead of session auth, It would not be wise to query the DB inside def process_request correct?

Does this mean i need to completely refactor the token Auth to grab from the redis store instead of the PG database?

jrief commented 8 years ago

ws4redis doesn't care which authentication system you're using. It requires the user object which is available in each request.

domface commented 8 years ago
    def process_request(self, request):
        request.session = None
        request.user = None
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
        if session_key is not None:
            engine = import_module(settings.SESSION_ENGINE)
            request.session = engine.SessionStore(session_key)
            request.user = SimpleLazyObject(lambda: get_user(request))

But according to your code here in wsgi_server.py it looks like you're getting the user visa vie the session_key stored in the Redis Cache

jrief commented 8 years ago

Yes, you're right. To retrieve the user (by auth token), we do not necessarily need an session-id. Please retry by unindenting the last line.

domface commented 8 years ago

I tried that already but got the following:

File "./ws4redis/wsgi_server.py", line 61, in <lambda>
    request.user = SimpleLazyObject(lambda: get_user(request))
  File "/usr/local/lib/python2.7/dist-packages/django/contrib/auth/__init__.py", line 167, in get_user
    user_id = _get_user_session_key(request)
  File "/usr/local/lib/python2.7/dist-packages/django/contrib/auth/__init__.py", line 59, in _get_user_session_key
    return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
TypeError: 'NoneType' object has no attribute '__getitem__'
domface commented 8 years ago

So it looks like a Session ID is needed, I am only providing Token Auth.

domface commented 8 years ago

Just for context, i'm making this call from an iOS device.

samirotiv commented 8 years ago

@jrief Firstly, thanks very much for your great work!!.

I'm facing the same issue - I'm using the Token Authentication scheme of the Django REST Framework and user messaging doesn't seem to work. I had encountered this a month ago, but was too busy to get into it.

Since I'm only using it for poll hints, temporarily, I am using only broadcast messages which also include the target user ID, which although is a very tacky solution, it works fine. I was going to get around to modify ws4redis, but didn't find the time.

Seems similar to #67

jrief commented 8 years ago

Whenever I have time, I will check this. For the moment, please be patient.

edwardotis commented 8 years ago

+1 I require Token Auth in my app

domface commented 8 years ago

I have a work around @edwardotis but it involves some refactoring to the default TokenSerializer.

When a user logs in/checks current user/updates details, i write the serialized user as such:

c = StrictRedis(connection_pool=redis_connection_pool) c.set('tokens:' + self.token.key, serialized_user)

then inside the wsgi_server.py file under ws4redis, i refactored the following function:

def process_request(self, request):
    request.session = None
    request.user = None
    if request.META['HTTP_AUTHORIZATION']:
        a = request.META['HTTP_AUTHORIZATION']
        array = a.split()
        token = array[1]
        request.user = json.loads(self._redis_connection.get('tokens:' + token).decode('utf8'))

thereby storing a JSON representation of the User object, each time a user logs in, updates his/her profile, or checks his/her profile, to ensure consistent data across data stores.

edwardotis commented 8 years ago

Thanks, @domface As much as I would like add a websockets endpoint to my django installation, I've actually decided to go with the 3rd party Pusher service for the time being. But I will revisit later on.

mlindemu commented 7 years ago

Any updates on supporting token-based authentication?

Mallfurion commented 6 years ago

UPDATE:

found a solution, thanks to the fact that you can specify inside the settings file the process_request function.

Thus, you will subscribe to a websocket by passing an extra query_param, token, with the value of the Authorization Token.

settings.py

WS4REDIS_PROCESS_REQUEST = 'project_path_to_function.process.request'

project_path_to_function.py

from django.core.exceptions import PermissionDenied
from rest_framework.authtoken.models import Token

def process_request(request):
    token = Token.objects.filter(key=request.GET.get('token')).first()
    if not token:
        PermissionDenied('Invalid Token')
    request.user = token.user
jrief commented 6 years ago

@Mallfurion would you mind to create a pull request for it?