-
Notifications
You must be signed in to change notification settings - Fork 506
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5e66b21
commit f8571a0
Showing
18 changed files
with
236 additions
and
160 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,5 @@ REDIS_DB=0 | |
|
||
HTTPS=false | ||
|
||
ENFORCE_2FA=false | ||
|
||
EMAIL_HOST=fir_fake_smtp | ||
EMAIL_PORT=1025 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
This module allows users to use 2FA when connecting to FIR. | ||
|
||
The module supports the following second-factors: | ||
- Yubikeys, which are validated against YubiCloud by default | ||
- Webauthn | ||
- TOTP | ||
|
||
## Install | ||
|
||
Follow the generic plugin installation instructions in [the FIR wiki](https://github.com/certsocietegenerale/FIR/wiki/Plugins). | ||
|
||
Once installed, please set the following settings in `production.py` | ||
|
||
``` | ||
ENFORCE_2FA = True # If False, 2FA will be enabled but not enforced | ||
LOGIN_URL = "two_factor:login" | ||
LOGIN_REDIRECT_URL = "two_factor:profile" | ||
MIDDLEWARE += ( | ||
"django_otp.middleware.OTPMiddleware", | ||
) | ||
INSTALLED_APPS += ( | ||
"django_otp", | ||
"django_otp.plugins.otp_static", | ||
"django_otp.plugins.otp_totp", | ||
"two_factor", | ||
"otp_yubikey", | ||
"two_factor.plugins.yubikey", # <- for yubikey capability | ||
"two_factor.plugins.webauthn", # <- for webauthn capability | ||
) | ||
# Webauthn Relying Party | ||
TWO_FACTOR_WEBAUTHN_RP_NAME = 'YOURFIRINSTALL' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import fir_auth_2fa.decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from django_otp.decorators import otp_required | ||
from django.conf import settings | ||
from django.contrib.auth import REDIRECT_FIELD_NAME | ||
|
||
import fir.decorators | ||
|
||
|
||
def fir_auth_required_2fa(view=None, redirect_field_name=None, login_url=None): | ||
if hasattr(settings, "ENFORCE_2FA") and settings.ENFORCE_2FA: | ||
decorator = otp_required( | ||
view=view, | ||
redirect_field_name=REDIRECT_FIELD_NAME, | ||
login_url=login_url, | ||
if_configured=False, | ||
) | ||
else: | ||
decorator = otp_required( | ||
view=view, | ||
redirect_field_name=REDIRECT_FIELD_NAME, | ||
login_url=login_url, | ||
if_configured=True, | ||
) | ||
|
||
return decorator | ||
|
||
|
||
# Patch decorator to enable 2FA | ||
fir.decorators.fir_auth_required = fir_auth_required_2fa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from two_factor.forms import AuthenticationTokenForm | ||
|
||
|
||
class CustomAuthenticationTokenForm(AuthenticationTokenForm): | ||
def __init__(self, user, initial_device, **kwargs): | ||
super(CustomAuthenticationTokenForm, self).__init__( | ||
user, initial_device, **kwargs | ||
) | ||
self.fields["otp_token"].widget.attrs.update({"class": "form-control"}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
django-otp-yubikey | ||
django-two-factor-auth[phonenumbers] | ||
django-two-factor-auth[webauthn] |
2 changes: 2 additions & 0 deletions
2
fir_auth_2fa/templates/fir_auth_2fa/plugins/user_profile_actions.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
{% load i18n %} | ||
<li><a href="{% url 'two_factor:profile' %}" id="user_manage_2fa"><i class="glyphicon glyphicon-phone"></i>{% trans "Manage 2FA" %}</a></li> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
fir_auth_2fa/templates/two_factor/core/setup_complete.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{% extends "two_factor/_base_focus.html" %} | ||
{% load i18n %} | ||
|
||
{% block content %} | ||
<h1>{% block title %}{% trans "Enable Two-Factor Authentication" %}{% endblock %}</h1> | ||
|
||
<p>{% blocktrans trimmed %}Congratulations, you've successfully enabled two-factor | ||
authentication.{% endblocktrans %}</p> | ||
|
||
{% if not phone_methods %} | ||
<p><a href="{% url 'dashboard:main' %}" | ||
class="btn btn-block btn-secondary">{% trans "Back to FIR homepage" %}</a></p> | ||
{% else %} | ||
<p>{% blocktrans trimmed %}However, it might happen that you don't have access to | ||
your primary token device. To enable account recovery, add a phone | ||
number.{% endblocktrans %}</p> | ||
|
||
<a href="{% url 'dashboard:main' %}" | ||
class="float-right btn btn-link">{% trans "Back to FIR homepage" %}</a> | ||
<p><a href="{% url 'two_factor:phone_create' %}" | ||
class="btn btn-success">{% trans "Add Phone Number" %}</a></p> | ||
{% endif %} | ||
|
||
{% endblock %} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from django.apps import apps | ||
from django.urls import include, re_path | ||
from two_factor.views import LoginView | ||
from two_factor.urls import urlpatterns as tf_urls | ||
import fir.urls as fir_urls | ||
from incidents import views as incidents_views | ||
from fir_auth_2fa import views | ||
|
||
|
||
# Remove the original login URL | ||
fir_urls.urlpatterns = [ | ||
x for x in fir_urls.urlpatterns if x.callback != incidents_views.user_login | ||
] | ||
|
||
custom_urls = [] | ||
for tf_url in tf_urls[0]: | ||
if getattr(tf_url, "name", "") != "login": | ||
custom_urls.append(tf_url) | ||
|
||
custom_urls.append( | ||
re_path( | ||
r"^account/login/$", | ||
view=views.CustomLoginView.as_view(), | ||
name="login", | ||
) | ||
) | ||
|
||
fir_urls.urlpatterns.append(re_path(r"", include((custom_urls, "two_factor")))) | ||
|
||
urlpatterns = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from django.conf import settings | ||
from django.utils.http import url_has_allowed_host_and_scheme | ||
from django.shortcuts import redirect, resolve_url | ||
from django.core.exceptions import ObjectDoesNotExist | ||
from django.contrib.auth import login, logout | ||
|
||
from two_factor import signals | ||
from two_factor.forms import AuthenticationTokenForm, BackupTokenForm | ||
from two_factor.views.core import LoginView | ||
from otp_yubikey.models import ValidationService | ||
|
||
from fir_auth_2fa.forms import CustomAuthenticationTokenForm | ||
from incidents.models import Profile | ||
from incidents.forms import CustomAuthenticationForm | ||
from incidents.views import init_session, log | ||
|
||
|
||
class CustomLoginView(LoginView): | ||
template_name = "two_factor/login.html" | ||
|
||
form_list = ( | ||
("auth", CustomAuthenticationForm), | ||
("token", CustomAuthenticationTokenForm), | ||
("backup", BackupTokenForm), | ||
) | ||
|
||
def __init__(self, **kwargs): | ||
try: | ||
|
||
if ValidationService.objects.count() == 0: | ||
# Validate Yubikey against YubiCloud by default | ||
ValidationService.objects.create( | ||
name="default", use_ssl=True, param_sl="", param_timeout="" | ||
) | ||
except ImportError: | ||
pass | ||
super(CustomLoginView, self).__init__(**kwargs) | ||
|
||
def post(self, *args, **kwargs): | ||
if not self.request.POST.get( | ||
"auth-remember", None | ||
) and not "token" in self.request.POST.get( | ||
"custom_login_view-current_step", [] | ||
): | ||
self.request.session.set_expiry(0) | ||
return super(CustomLoginView, self).post(**kwargs) | ||
|
||
def done(self, form_list, **kwargs): | ||
""" | ||
Login the user and redirect to the desired page. | ||
""" | ||
login(self.request, self.get_user()) | ||
|
||
redirect_to = self.request.POST.get( | ||
self.redirect_field_name, self.request.GET.get(self.redirect_field_name, "") | ||
) | ||
if not url_has_allowed_host_and_scheme( | ||
url=redirect_to, allowed_hosts=self.request.get_host() | ||
): | ||
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL) | ||
|
||
is_auth = False | ||
user = self.get_user() | ||
device = getattr(self.get_user(), "otp_device", None) | ||
if device: | ||
signals.user_verified.send( | ||
sender=__name__, | ||
request=self.request, | ||
user=self.get_user(), | ||
device=device, | ||
) | ||
redirect_to = resolve_url("dashboard:main") | ||
is_auth = True | ||
elif hasattr(settings, "ENFORCE_2FA") and settings.ENFORCE_2FA: | ||
redirect_to = resolve_url("two_factor:profile") | ||
else: | ||
redirect_to = resolve_url("dashboard:main") | ||
is_auth = True | ||
try: | ||
Profile.objects.get(user=user) | ||
except ObjectDoesNotExist: | ||
profile = Profile() | ||
profile.user = user | ||
profile.hide_closed = False | ||
profile.incident_number = 50 | ||
profile.save() | ||
if user.is_active: | ||
log("Login success", user) | ||
init_session(self.request) | ||
return redirect(redirect_to) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.