valohai / django-allauth-2fa

Two-factor authentication for Django Allauth
Other
212 stars 50 forks source link

TypeError at /accounts/login/: Object of type 'UUID' is not JSON serializable #64

Closed chromakey closed 5 years ago

chromakey commented 6 years ago

Howdy, I have an existing project that's been using django-allauth successfully for several months now. I've setup django-allauth-2fa and I was able to successfully register a device. However, when I go to login, I get the following exception and traceback. I am using a UUIDField for my User model primary key. I am requiring that all users have 2FA enabled.

Thanks for all of your work on this project!

Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/accounts/login/

Django Version: 1.11.14
Python Version: 3.6.1

Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django_otp.middleware.OTPMiddleware',
 'allauth_2fa.middleware.AllauthTwoFactorMiddleware',
 'project.users.middleware.RequireSuperuser2FAMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'request_logging.middleware.LoggingMiddleware',
 'auditlog.middleware.AuditlogMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware']

Traceback:

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/utils/deprecation.py" in __call__
  142.             response = self.process_response(request, response)

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/sessions/middleware.py" in process_response
  58.                             request.session.save()

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py" in save
  81.             return self.create()

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py" in create
  54.                 self.save(must_create=True)

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py" in save
  83.         obj = self.create_model_instance(data)

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py" in create_model_instance
  69.             session_data=self.encode(data),

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py" in encode
  98.         serialized = self.serializer().dumps(session_dict)

File "/Users/chromakey/.virtualenvs/project/lib/python3.6/site-packages/django/core/signing.py" in dumps
  93.         return json.dumps(obj, separators=(',', ':')).encode('latin-1')

File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py" in dumps
  238.         **kw).encode(obj)

File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py" in encode
  199.         chunks = self.iterencode(o, _one_shot=True)

File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py" in iterencode
  257.         return _iterencode(o, 0)

File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py" in default
  180.                         o.__class__.__name__)

Exception Type: TypeError at /accounts/login/
Exception Value: Object of type 'UUID' is not JSON serializable
clokep commented 6 years ago

This is probably happening because we add user.id to the session (see https://github.com/percipient/django-allauth-2fa/blob/6d666d634ded380c4a7f660ac5a729fae095ffb2/allauth_2fa/adapter.py#L22-L24), which I guess is of type UUID? (I've never used a UUIDField, is the value a UUID object, not a string?)

It might work to cast to a string when adding it to the session, like: request.session['allauth_2fa_user_id'] = str(user.id)

chromakey commented 6 years ago

That indeed worked. Thanks! I'll submit a PR today with the change.

clokep commented 6 years ago

Awesome! 💥 Please include tests with your PR! I'll try to review it within the next few days.

chromakey commented 6 years ago

I'm not sure how I'd write a good test in the current context. Since the current user model defaults to using IntegerField as the ID/PK, I supposed I'd have to write a dummy user model?

clokep commented 6 years ago

I'll think a bit about how to test this.

teevyne commented 3 years ago

I'll think a bit about how to test this.

@clokep Hi Patrick. Thank you for this response. I have run into a similar issue but this is when I try to login. The registration part works fine, but logging in isn't quite working. My login parameters are email and password

What could I be getting wrong?