Initial mfa support (for internal users) #93591
@ -8,7 +8,7 @@
|
|||||||
{% with form=form|add_form_classes %}
|
{% with form=form|add_form_classes %}
|
||||||
<form method="POST" id="u2f-authenticate-form">{% csrf_token %}
|
<form method="POST" id="u2f-authenticate-form">{% csrf_token %}
|
||||||
<fieldset class="mb-4">
|
<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 %}
|
{% with field=form.otp_trust_agent %}
|
||||||
{% include "components/forms/field.html" with with_help_text=True %}
|
{% include "components/forms/field.html" with with_help_text=True %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
@ -23,6 +23,7 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{ form.non_field_errors }}
|
{{ form.non_field_errors }}
|
||||||
|
<div id="webauthn-error"></div>
|
||||||
</form>
|
</form>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% if devices.totp %}
|
{% if devices.totp %}
|
||||||
@ -35,9 +36,13 @@
|
|||||||
const form = document.getElementById('u2f-authenticate-form');
|
const form = document.getElementById('u2f-authenticate-form');
|
||||||
const responseInput = document.getElementById('id_response');
|
const responseInput = document.getElementById('id_response');
|
||||||
const requestOptions = JSON.parse(responseInput.getAttribute('request-options'));
|
const requestOptions = JSON.parse(responseInput.getAttribute('request-options'));
|
||||||
(async function() {
|
webauthnJSON.get(requestOptions).then(
|
||||||
const credential = await webauthnJSON.get(requestOptions);
|
(credential) => {
|
||||||
responseInput.value = JSON.stringify(credential);
|
responseInput.value = JSON.stringify(credential);
|
||||||
form.submit();
|
form.submit();
|
||||||
})();
|
},
|
||||||
|
(error) => {
|
||||||
|
document.getElementById('webauthn-error').innerText = 'Something went wrong: ' + error;
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
{% block page_title %}Sign in{% endblock %}
|
{% block page_title %}Sign in{% endblock %}
|
||||||
|
|
||||||
{% block form %}
|
{% block form %}
|
||||||
{% if is_authentication_form %}
|
{% if form_type == 'login' %}
|
||||||
{% include 'bid_main/components/login_form.html' %}
|
{% include 'bid_main/components/login_form.html' %}
|
||||||
{% elif is_mfa_form %}
|
{% elif form_type == 'mfa' %}
|
||||||
{% include 'bid_main/components/mfa_form.html' %}
|
{% include 'bid_main/components/mfa_form.html' %}
|
||||||
{% elif is_u2f_form %}
|
{% elif form_type == 'u2f' %}
|
||||||
{% include 'bid_main/components/u2f_form.html' %}
|
{% include 'bid_main/components/u2f_form.html' %}
|
||||||
|
{% else %}
|
||||||
|
<div class="bix box">Something went wrong</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock form %}
|
{% endblock form %}
|
||||||
|
@ -10,7 +10,7 @@ import urllib.parse
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import views as auth_views, logout, get_user_model
|
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.utils.translation import gettext as _
|
||||||
from django.db import transaction, IntegrityError
|
from django.db import transaction, IntegrityError
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
@ -96,15 +96,19 @@ class LoginView(mixins.RedirectToPrivacyAgreeMixin, mixins.PageIdMixin, otp_agen
|
|||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
self.find_oauth_flow(ctx)
|
self.find_oauth_flow(ctx)
|
||||||
form = self.get_form()
|
form = self.get_form()
|
||||||
|
form_type = None
|
||||||
if isinstance(form, U2fAuthenticateForm):
|
if isinstance(form, U2fAuthenticateForm):
|
||||||
ctx["devices"] = self.request.user.mfa_devices_per_category()
|
ctx["devices"] = self.request.user.mfa_devices_per_category()
|
||||||
ctx["is_u2f_form"] = True
|
form_type = 'u2f'
|
||||||
elif isinstance(form, MfaAuthenticateForm):
|
elif isinstance(form, MfaAuthenticateForm):
|
||||||
ctx["devices"] = self.request.user.mfa_devices_per_category()
|
ctx["devices"] = self.request.user.mfa_devices_per_category()
|
||||||
ctx["is_mfa_form"] = True
|
|
||||||
ctx["use_recovery"] = self._use_recovery()
|
ctx["use_recovery"] = self._use_recovery()
|
||||||
|
form_type = 'mfa'
|
||||||
|
elif isinstance(form, forms.AuthenticationForm):
|
||||||
|
form_type = 'login'
|
||||||
else:
|
else:
|
||||||
ctx["is_authentication_form"] = isinstance(form, forms.AuthenticationForm)
|
raise ImproperlyConfigured('unexpected form object')
|
||||||
|
ctx["form_type"] = form_type
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
def get_form(self):
|
def get_form(self):
|
||||||
@ -120,7 +124,7 @@ class LoginView(mixins.RedirectToPrivacyAgreeMixin, mixins.PageIdMixin, otp_agen
|
|||||||
kwargs['rp_id'] = rp_id
|
kwargs['rp_id'] = rp_id
|
||||||
kwargs['state'] = dict(state)
|
kwargs['state'] = dict(state)
|
||||||
return U2fAuthenticateForm(**kwargs)
|
return U2fAuthenticateForm(**kwargs)
|
||||||
# this will switch between MfaForm and AuthenticationForm
|
# this will switch between MfaAuthenticateForm and AuthenticationForm
|
||||||
return super().get_form()
|
return super().get_form()
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user