core: mfa cleanup session after successful login
This commit is contained in:
parent
c140c6f524
commit
0c53a95b06
|
@ -3,7 +3,7 @@ from logging import getLogger
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import login
|
from django.contrib.auth import login
|
||||||
from django.http import Http404
|
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||||
from django.shortcuts import get_object_or_404, redirect, reverse
|
from django.shortcuts import get_object_or_404, redirect, reverse
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ from passbook.lib.utils.reflection import class_to_path, path_to_class
|
||||||
|
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
class MultiFactorAuthenticator(View):
|
|
||||||
|
class MultiFactorAuthenticator(UserPassesTestMixin, View):
|
||||||
"""Wizard-like Multi-factor authenticator"""
|
"""Wizard-like Multi-factor authenticator"""
|
||||||
|
|
||||||
SESSION_FACTOR = 'passbook_factor'
|
SESSION_FACTOR = 'passbook_factor'
|
||||||
|
@ -28,13 +29,23 @@ class MultiFactorAuthenticator(View):
|
||||||
|
|
||||||
_current_factor = None
|
_current_factor = None
|
||||||
|
|
||||||
|
# Allow only not authenticated users to login
|
||||||
|
def test_func(self):
|
||||||
|
return self.request.user.is_authenticated is False
|
||||||
|
|
||||||
|
def handle_no_permission(self):
|
||||||
|
if 'next' in self.request.GET:
|
||||||
|
return redirect(self.request.GET.get('next'))
|
||||||
|
return redirect(reverse('passbook_core:overview'))
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
# Extract pending user from session (only remember uid)
|
# Extract pending user from session (only remember uid)
|
||||||
if MultiFactorAuthenticator.SESSION_PENDING_USER in request.session:
|
if MultiFactorAuthenticator.SESSION_PENDING_USER in request.session:
|
||||||
self.pending_user = get_object_or_404(
|
self.pending_user = get_object_or_404(
|
||||||
User, id=self.request.session[MultiFactorAuthenticator.SESSION_PENDING_USER])
|
User, id=self.request.session[MultiFactorAuthenticator.SESSION_PENDING_USER])
|
||||||
else:
|
else:
|
||||||
raise Http404
|
# No Pending user, redirect to login screen
|
||||||
|
return redirect(reverse('passbook_core:auth-login'))
|
||||||
# Write pending factors to session
|
# Write pending factors to session
|
||||||
if MultiFactorAuthenticator.SESSION_PENDING_FACTORS in request.session:
|
if MultiFactorAuthenticator.SESSION_PENDING_FACTORS in request.session:
|
||||||
self.pending_factors = request.session[MultiFactorAuthenticator.SESSION_PENDING_FACTORS]
|
self.pending_factors = request.session[MultiFactorAuthenticator.SESSION_PENDING_FACTORS]
|
||||||
|
@ -80,7 +91,8 @@ class MultiFactorAuthenticator(View):
|
||||||
return self._user_passed()
|
return self._user_passed()
|
||||||
|
|
||||||
def user_invalid(self):
|
def user_invalid(self):
|
||||||
"""Show error message, user could not be authenticated"""
|
"""Show error message, user cannot login.
|
||||||
|
This should only be shown if user authenticated successfully, but is disabled/locked/etc"""
|
||||||
LOGGER.debug("User invalid")
|
LOGGER.debug("User invalid")
|
||||||
return redirect(reverse('passbook_core:mfa-denied'))
|
return redirect(reverse('passbook_core:mfa-denied'))
|
||||||
|
|
||||||
|
@ -90,7 +102,18 @@ class MultiFactorAuthenticator(View):
|
||||||
backend = self.request.session[MultiFactorAuthenticator.SESSION_USER_BACKEND]
|
backend = self.request.session[MultiFactorAuthenticator.SESSION_USER_BACKEND]
|
||||||
login(self.request, self.pending_user, backend=backend)
|
login(self.request, self.pending_user, backend=backend)
|
||||||
LOGGER.debug("Logged in user %s", self.pending_user)
|
LOGGER.debug("Logged in user %s", self.pending_user)
|
||||||
|
# Cleanup
|
||||||
|
self._cleanup()
|
||||||
return redirect(reverse('passbook_core:overview'))
|
return redirect(reverse('passbook_core:overview'))
|
||||||
|
|
||||||
|
def _cleanup(self):
|
||||||
|
"""Remove temporary data from session"""
|
||||||
|
session_keys = ['SESSION_FACTOR', 'SESSION_PENDING_FACTORS',
|
||||||
|
'SESSION_PENDING_USER', 'SESSION_USER_BACKEND', ]
|
||||||
|
for key in session_keys:
|
||||||
|
if key in self.request.session:
|
||||||
|
del self.request.session[key]
|
||||||
|
LOGGER.debug("Cleaned up sessions")
|
||||||
|
|
||||||
class MFAPermissionDeniedView(PermissionDeniedView):
|
class MFAPermissionDeniedView(PermissionDeniedView):
|
||||||
"""User could not be authenticated"""
|
"""User could not be authenticated"""
|
||||||
|
|
Reference in New Issue