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
3 changed files with 25 additions and 14 deletions
Showing only changes of commit ac496f040a - Show all commits

View File

@ -8,7 +8,7 @@
{% with form=form|add_form_classes %}
<form method="POST" id="u2f-authenticate-form">{% csrf_token %}
<fieldset class="mb-4">
<p>Use a security key.</p>
<p>Please use a security key you have configured. Tick the checkbox below before using the key</p>
{% with field=form.otp_trust_agent %}
{% include "components/forms/field.html" with with_help_text=True %}
{% endwith %}
@ -23,6 +23,7 @@
{% endwith %}
</fieldset>
{{ form.non_field_errors }}
<div id="webauthn-error"></div>
</form>
{% endwith %}
{% if devices.totp %}
@ -35,9 +36,13 @@
const form = document.getElementById('u2f-authenticate-form');
const responseInput = document.getElementById('id_response');
const requestOptions = JSON.parse(responseInput.getAttribute('request-options'));
(async function() {
const credential = await webauthnJSON.get(requestOptions);
webauthnJSON.get(requestOptions).then(
(credential) => {
responseInput.value = JSON.stringify(credential);
form.submit();
})();
},
(error) => {
document.getElementById('webauthn-error').innerText = 'Something went wrong: ' + error;
}
);
</script>

View File

@ -3,11 +3,13 @@
{% block page_title %}Sign in{% endblock %}
{% block form %}
{% if is_authentication_form %}
{% if form_type == 'login' %}
{% include 'bid_main/components/login_form.html' %}
{% elif is_mfa_form %}
{% elif form_type == 'mfa' %}
{% include 'bid_main/components/mfa_form.html' %}
{% elif is_u2f_form %}
{% elif form_type == 'u2f' %}
{% include 'bid_main/components/u2f_form.html' %}
{% else %}
<div class="bix box">Something went wrong</div>
{% endif %}
{% endblock form %}

View File

@ -10,7 +10,7 @@ import urllib.parse
from django.conf import settings
from django.contrib.auth import views as auth_views, logout, get_user_model
from django.core.exceptions import ValidationError
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.utils.translation import gettext as _
from django.db import transaction, IntegrityError
from django.db.models import Count
@ -96,15 +96,19 @@ class LoginView(mixins.RedirectToPrivacyAgreeMixin, mixins.PageIdMixin, otp_agen
ctx = super().get_context_data(**kwargs)
self.find_oauth_flow(ctx)
form = self.get_form()
form_type = None
if isinstance(form, U2fAuthenticateForm):
ctx["devices"] = self.request.user.mfa_devices_per_category()
ctx["is_u2f_form"] = True
form_type = 'u2f'
elif isinstance(form, MfaAuthenticateForm):
ctx["devices"] = self.request.user.mfa_devices_per_category()
ctx["is_mfa_form"] = True
ctx["use_recovery"] = self._use_recovery()
form_type = 'mfa'
elif isinstance(form, forms.AuthenticationForm):
form_type = 'login'
else:
ctx["is_authentication_form"] = isinstance(form, forms.AuthenticationForm)
raise ImproperlyConfigured('unexpected form object')
ctx["form_type"] = form_type
return ctx
def get_form(self):
@ -120,7 +124,7 @@ class LoginView(mixins.RedirectToPrivacyAgreeMixin, mixins.PageIdMixin, otp_agen
kwargs['rp_id'] = rp_id
kwargs['state'] = dict(state)
return U2fAuthenticateForm(**kwargs)
# this will switch between MfaForm and AuthenticationForm
# this will switch between MfaAuthenticateForm and AuthenticationForm
return super().get_form()
def get_form_kwargs(self):