50 lines
2.1 KiB
Python
50 lines
2.1 KiB
Python
"""passbook multi-factor authentication engine"""
|
|
from logging import getLogger
|
|
|
|
from django.contrib.auth import authenticate
|
|
from django.core.exceptions import PermissionDenied
|
|
from django.forms.utils import ErrorList
|
|
from django.utils.translation import gettext as _
|
|
from django.views.generic import FormView
|
|
|
|
from passbook.core.auth.factor import AuthenticationFactor
|
|
from passbook.core.auth.mfa import MultiFactorAuthenticator
|
|
from passbook.core.forms.authentication import AuthenticationBackendFactorForm
|
|
from passbook.lib.config import CONFIG
|
|
|
|
LOGGER = getLogger(__name__)
|
|
|
|
|
|
class AuthenticationBackendFactor(FormView, AuthenticationFactor):
|
|
"""Authentication factor which authenticates against django's AuthBackend"""
|
|
|
|
form_class = AuthenticationBackendFactorForm
|
|
template_name = 'login/factors/backend.html'
|
|
|
|
def form_valid(self, form):
|
|
"""Authenticate against django's authentication backend"""
|
|
uid_fields = CONFIG.y('passbook.uid_fields')
|
|
kwargs = {
|
|
'password': form.cleaned_data.get('password'),
|
|
}
|
|
for uid_field in uid_fields:
|
|
kwargs[uid_field] = getattr(self.authenticator.pending_user, uid_field)
|
|
try:
|
|
user = authenticate(self.request, **kwargs)
|
|
if user:
|
|
# User instance returned from authenticate() has .backend property set
|
|
self.authenticator.pending_user = user
|
|
self.request.session[MultiFactorAuthenticator.SESSION_USER_BACKEND] = user.backend
|
|
return self.authenticator.user_ok()
|
|
# No user was found -> invalid credentials
|
|
LOGGER.debug("Invalid credentials")
|
|
# Manually inject error into form
|
|
# pylint: disable=protected-access
|
|
errors = form._errors.setdefault("password", ErrorList())
|
|
errors.append(_("Invalid password"))
|
|
return self.form_invalid(form)
|
|
except PermissionDenied:
|
|
# User was found, but permission was denied (i.e. user is not active)
|
|
LOGGER.debug("Denied access to %s", kwargs)
|
|
return self.authenticator.user_invalid()
|