Skip to content

Commit

Permalink
Add 2FA to the admin site
Browse files Browse the repository at this point in the history
Add possibility to enable two-factor authentication for the admin site.
  • Loading branch information
japauliina authored and mhieta committed Aug 27, 2024
1 parent 3712941 commit 92c20ea
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 0 deletions.
2 changes: 2 additions & 0 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ djangorestframework
djangorestframework-jsonp
django-filter
django-modeltranslation
django-two-factor-auth
django-two-factor-auth[phonenumbers]
flake8
requests
requests_cache
Expand Down
19 changes: 19 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@ django==5.1
# django-cors-headers
# django-extensions
# django-filter
# django-formtools
# django-js-asset
# django-modeltranslation
# django-munigeo
# django-otp
# django-phonenumber-field
# django-polymorphic
# django-two-factor-auth
# djangorestframework
# drf-spectacular
django-cors-headers==4.4.0
Expand All @@ -54,6 +58,8 @@ django-extensions==3.2.3
# via -r requirements.in
django-filter==24.3
# via -r requirements.in
django-formtools==2.5.1
# via django-two-factor-auth
django-js-asset==2.2.0
# via django-mptt
django-modeltranslation==0.19.7
Expand All @@ -66,8 +72,14 @@ django-mptt==0.16.0
# django-munigeo
django-munigeo @ git+https://github.com/City-of-Helsinki/[email protected]
# via -r requirements.in
django-otp==1.5.2
# via django-two-factor-auth
django-phonenumber-field==8.0.0
# via django-two-factor-auth
django-polymorphic==3.1.0
# via -r requirements.in
django-two-factor-auth[phonenumbers]==1.17.0
# via -r requirements.in
djangorestframework==3.15.2
# via
# -r requirements.in
Expand Down Expand Up @@ -125,6 +137,8 @@ pathspec==0.12.1
# via black
pep8-naming==0.14.1
# via -r requirements.in
phonenumbers==8.13.43
# via django-two-factor-auth
pip-tools==7.4.1
# via -r requirements.in
platformdirs==4.2.2
Expand All @@ -139,6 +153,8 @@ pycodestyle==2.12.1
# via flake8
pyflakes==3.2.0
# via flake8
pypng==0.20220715.0
# via qrcode
pyproject-hooks==1.1.0
# via
# build
Expand All @@ -159,6 +175,8 @@ pyyaml==6.0.2
# via
# django-munigeo
# drf-spectacular
qrcode==7.4.2
# via django-two-factor-auth
referencing==0.35.1
# via
# jsonschema
Expand Down Expand Up @@ -202,6 +220,7 @@ typing-extensions==4.12.2
# black
# cattrs
# django-modeltranslation
# qrcode
tzdata==2024.1
# via -r requirements.in
uritemplate==4.1.1
Expand Down
30 changes: 30 additions & 0 deletions services/templates/two_factor/_base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" media="screen">
<script defer src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script defer src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/js/bootstrap.min.js"></script>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh; /* Full viewport height */
margin: 0; /* Remove default margin */
}
.container {
transform: translateY(-60px);
}
</style>
{% block extra_media %}{% endblock %}
</head>
<body>
{% block content_wrapper %}
<div class="container">
{% block content %}{% endblock %}
</div>
{% endblock %}
</body>
</html>
36 changes: 36 additions & 0 deletions smbackend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@
SEARCH_LOG_LEVEL=(str, "INFO"),
GEO_SEARCH_LOCATION=(str, ""),
GEO_SEARCH_API_KEY=(str, ""),
EMAIL_USE_TLS=(bool, True),
EMAIL_HOST=(str, None),
EMAIL_PORT=(int, None),
EMAIL_TIMEOUT=(int, None),
EMAIL_HOST_USER=(str, None),
EMAIL_HOST_PASSWORD=(str, None),
OTP_EMAIL_SENDER=(str, None),
)

env_path = BASE_DIR / ".env"
Expand All @@ -60,6 +67,13 @@
DJANGO_LOG_LEVEL = env("DJANGO_LOG_LEVEL")
IMPORT_LOG_LEVEL = env("IMPORT_LOG_LEVEL")
SEARCH_LOG_LEVEL = env("SEARCH_LOG_LEVEL")
EMAIL_USE_TLS = env("EMAIL_USE_TLS")
EMAIL_HOST = env("EMAIL_HOST")
EMAIL_PORT = env("EMAIL_PORT")
EMAIL_TIMEOUT = env("EMAIL_TIMEOUT")
EMAIL_HOST_USER = env("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD")
OTP_EMAIL_SENDER = env("OTP_EMAIL_SENDER")

# Application definition
INSTALLED_APPS = [
Expand All @@ -82,6 +96,13 @@
"services.apps.ServicesConfig",
"observations",
"drf_spectacular",
# Two-factor authentication
"django_otp",
"django_otp.plugins.otp_static",
"django_otp.plugins.otp_totp",
"django_otp.plugins.otp_email",
"two_factor",
"two_factor.plugins.email",
]

if env("ADDITIONAL_INSTALLED_APPS"):
Expand All @@ -100,6 +121,7 @@
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django_otp.middleware.OTPMiddleware",
]

if env("ADDITIONAL_MIDDLEWARE"):
Expand Down Expand Up @@ -252,6 +274,7 @@ def gettext(s):
},
"handlers": {
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "timestamped_named",
},
Expand All @@ -260,6 +283,10 @@ def gettext(s):
"django": {"handlers": ["console"], "level": DJANGO_LOG_LEVEL},
"services.search": {"handlers": ["console"], "level": SEARCH_LOG_LEVEL},
"services.management": {"handlers": ["console"], "level": IMPORT_LOG_LEVEL},
"two_factor": {
"handlers": ["console"],
"level": "INFO",
},
},
}

Expand Down Expand Up @@ -287,3 +314,12 @@ def gettext(s):
"VERSION": None,
"SERVE_INCLUDE_SCHEMA": False,
}

# Two-factor authentication settings
LOGIN_URL = "two_factor:login"
OTP_EMAIL_SUBJECT = "Palvelukartta - kirjautumistunniste"

if DEBUG:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
else:
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
2 changes: 2 additions & 0 deletions smbackend/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
)
from munigeo.api import all_views as munigeo_views
from rest_framework import routers
from two_factor.urls import urlpatterns as tf_urls

from observations.api import views as observations_views
from observations.views import obtain_auth_token
Expand Down Expand Up @@ -77,4 +78,5 @@ def readiness(*args, **kwargs):
"schema/redoc/", SpectacularRedocView.as_view(url_name="schema"), name="redoc"
),
re_path(r"", include(shortcutter_urls)),
re_path("", include(tf_urls)),
]

0 comments on commit 92c20ea

Please sign in to comment.