Initial mfa support (for internal users) #93591

Merged
Oleg-Komarov merged 46 commits from mfa into main 2024-08-29 11:44:06 +02:00
4 changed files with 13 additions and 12 deletions
Showing only changes of commit 9d92e5f807 - Show all commits

View File

@ -18,7 +18,7 @@ import qrcode
from . import mixins
from mfa.fido2 import register_begin
from mfa.forms import DisableMfaForm, TotpMfaForm, U2fMfaForm
from mfa.forms import DisableMfaForm, TotpRegisterForm, U2fRegisterForm
from mfa.models import EncryptedRecoveryDevice, EncryptedTOTPDevice, U2fDevice, devices_for_user
import bid_main.tasks
@ -97,7 +97,7 @@ class InvalidateRecoveryView(mixins.MfaRequiredIfConfiguredMixin, View):
class TotpView(mixins.MfaRequiredIfConfiguredMixin, FormView):
form_class = TotpMfaForm
form_class = TotpRegisterForm
success_url = reverse_lazy('bid_main:mfa')
template_name = "bid_main/mfa/totp.html"
@ -135,7 +135,7 @@ class TotpView(mixins.MfaRequiredIfConfiguredMixin, FormView):
class U2fView(mixins.MfaRequiredIfConfiguredMixin, FormView):
form_class = U2fMfaForm
form_class = U2fRegisterForm
success_url = reverse_lazy('bid_main:mfa')
template_name = "bid_main/mfa/u2f.html"

View File

@ -32,7 +32,7 @@ from .. import forms, email
from . import mixins
from bid_main.email import send_verify_address
from mfa.fido2 import authenticate_begin
from mfa.forms import MfaForm, U2fForm
from mfa.forms import MfaAuthenticateForm, U2fAuthenticateForm
import bid_main.file_utils
User = get_user_model()
@ -78,7 +78,7 @@ class LoginView(mixins.RedirectToPrivacyAgreeMixin, mixins.PageIdMixin, otp_agen
"""Shows the login view."""
otp_authentication_form = forms.AuthenticationForm
otp_token_form = MfaForm
otp_token_form = MfaAuthenticateForm
page_id = "login"
redirect_authenticated_user = False
success_url_allowed_hosts = settings.NEXT_REDIR_AFTER_LOGIN_ALLOWED_HOSTS
@ -96,10 +96,10 @@ class LoginView(mixins.RedirectToPrivacyAgreeMixin, mixins.PageIdMixin, otp_agen
ctx = super().get_context_data(**kwargs)
self.find_oauth_flow(ctx)
form = self.get_form()
if isinstance(form, U2fForm):
if isinstance(form, U2fAuthenticateForm):
ctx["devices"] = self.request.user.mfa_devices_per_category()
ctx["is_u2f_form"] = True
elif isinstance(form, MfaForm):
elif isinstance(form, MfaAuthenticateForm):
ctx["devices"] = self.request.user.mfa_devices_per_category()
ctx["is_mfa_form"] = True
ctx["use_recovery"] = self._use_recovery()
@ -119,7 +119,7 @@ class LoginView(mixins.RedirectToPrivacyAgreeMixin, mixins.PageIdMixin, otp_agen
kwargs['request_options'] = json.dumps(dict(request_options))
kwargs['rp_id'] = rp_id
kwargs['state'] = dict(state)
return U2fForm(**kwargs)
return U2fAuthenticateForm(**kwargs)
# this will switch between MfaForm and AuthenticationForm
return super().get_form()

View File

@ -0,0 +1 @@
default_app_config = "%s.apps.MfaConfig" % __name__

View File

@ -27,7 +27,7 @@ def _verify_signature(payload, signature, max_age=3600):
return False
class MfaForm(OTPTokenForm):
class MfaAuthenticateForm(OTPTokenForm):
"""Restyle the form widgets to do less work in the template."""
def __init__(self, *args, **kwargs):
@ -73,7 +73,7 @@ class MfaForm(OTPTokenForm):
)
class U2fForm(OTPAgentFormMixin, forms.Form):
class U2fAuthenticateForm(OTPAgentFormMixin, forms.Form):
otp_trust_agent = forms.BooleanField(
help_text=_(
f"We won't ask for MFA on this device in the next {settings.AGENT_TRUST_DAYS} days. "
@ -145,7 +145,7 @@ class DisableMfaForm(forms.Form):
)
class TotpMfaForm(forms.Form):
class TotpRegisterForm(forms.Form):
code = forms.CharField(
validators=[RegexValidator(r'^[0-9]{6}$')],
widget=forms.TextInput(
@ -190,7 +190,7 @@ class TotpMfaForm(forms.Form):
EncryptedTOTPDevice.objects.create(encrypted_key=key, key='', name=name, user=self.user)
class U2fMfaForm(forms.Form):
class U2fRegisterForm(forms.Form):
credential = forms.JSONField(widget=forms.HiddenInput)
name = forms.CharField(
max_length=U2fDevice._meta.get_field('name').max_length,