django-websocket-redis
django-websocket-redis copied to clipboard
Using Token Auth for my app instead of Sessions
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?
ws4redis doesn't care which authentication system you're using. It requires the user object which is available in each request.
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
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.
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__'
So it looks like a Session ID is needed, I am only providing Token Auth.
Just for context, i'm making this call from an iOS device.
@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
Whenever I have time, I will check this. For the moment, please be patient.
+1 I require Token Auth in my app
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.
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.
Any updates on supporting token-based authentication?
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
@Mallfurion would you mind to create a pull request for it?