diff --git a/CHANGELOG b/CHANGELOG
index 88dca169f76a71f2a612d3afaacf89b134e9dd01..deb5ceede55b54c2c9d43e2e69bebf2074972d97 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,7 @@ smasch (1.0.0~alpha.1-0) unstable; urgency=low
     (#285)
   * small improvement: all configuration options that are not obligatory are 
     moved to configuration panel (#343)
+  * small improvement: 2FA can be configured to be required option (#358)
   
  -- Piotr Gawron <piotr.gawron@uni.lu>  Tue, 10 Nov 2020 14:00:00 +0200
 
diff --git a/smash/smash/local_settings.py.template b/smash/smash/local_settings.py.template
index 79c90e5220130d1e6ea9467b312d3edf30beee9b..fb44fbe9517d7b10898b1f5ae955843bed55ef06 100644
--- a/smash/smash/local_settings.py.template
+++ b/smash/smash/local_settings.py.template
@@ -76,3 +76,7 @@ LOGGING = {
 }
 
 TWO_FACTOR_SMS_GATEWAY = "web.nexmo_gateway.Nexmo"
+
+# whether 2 steps authentication is mandatory to access the system
+
+FORCE_2FA = True
diff --git a/smash/smash/middleware/__init__.py b/smash/smash/middleware/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..eea436a3790f7fd77b1cf18c6f5c5ae198e7dd6f
--- /dev/null
+++ b/smash/smash/middleware/__init__.py
@@ -0,0 +1,3 @@
+import logging
+
+logger = logging.getLogger(__name__)
diff --git a/smash/smash/middleware/force_2fa_middleware.py b/smash/smash/middleware/force_2fa_middleware.py
new file mode 100644
index 0000000000000000000000000000000000000000..21de43603e166d84d043fa403840357b0a45922b
--- /dev/null
+++ b/smash/smash/middleware/force_2fa_middleware.py
@@ -0,0 +1,27 @@
+import logging
+
+from django.contrib import messages
+from django.shortcuts import redirect
+
+logger = logging.getLogger(__name__)
+
+
+class Force2FAMiddleware:
+    """
+    Middleware restricting access to users with 2 factors authentication enabled
+    Redirects to 2fa section if not enabled
+    """
+
+    def __init__(self, get_response):
+        self.get_response = get_response
+
+    def __call__(self, request):
+        """
+        If user is authenticated and user is not verified (2fa not enabled) and we are in one of the 2fa setting pages
+        we redirect to the 2fa profile page
+        """
+        if request.user.is_authenticated and not request.user.is_verified() and 'two_factor' not in request.path:
+            messages.add_message(request, messages.WARNING,
+                                 '2 factors authentication must be enabled to use this system')
+            return redirect('two_factor:profile')
+        return self.get_response(request)
diff --git a/smash/smash/settings.py b/smash/smash/settings.py
index 15be4ea9c4cd68270d4226892658989016d80985..0b20f9916893b6e782d9aed6fe15fe898a3ae558 100644
--- a/smash/smash/settings.py
+++ b/smash/smash/settings.py
@@ -24,6 +24,9 @@ WSGI_APPLICATION = 'smash.wsgi.application'
 
 SERVE_STATIC = False
 
+# whether 2 steps authentication is mandatory to access the system
+FORCE_2FA = False
+
 # Application definition
 
 INSTALLED_APPS = [
@@ -145,3 +148,5 @@ from .local_settings import *
 if not SERVE_STATIC:
     MIDDLEWARE.remove('whitenoise.middleware.WhiteNoiseMiddleware')
 
+if FORCE_2FA:
+    MIDDLEWARE.append('smash.middleware.force_2fa_middleware.Force2FAMiddleware')
diff --git a/smash/web/tests/test_enforce_2fa.py b/smash/web/tests/test_enforce_2fa.py
new file mode 100644
index 0000000000000000000000000000000000000000..0affc9b1708b360feb079b12e3e0c09718260e01
--- /dev/null
+++ b/smash/web/tests/test_enforce_2fa.py
@@ -0,0 +1,55 @@
+# coding=utf-8
+from unittest.mock import Mock
+
+from django.http import HttpResponseRedirect
+from django.test import TestCase
+
+from smash.middleware.force_2fa_middleware import Force2FAMiddleware
+
+NOT_REDIRECTED = "Not redirected"
+
+
+class TestForce2FAMiddleware(TestCase):
+
+    def setUp(self):
+        self.middleware = Force2FAMiddleware(lambda x: NOT_REDIRECTED)
+
+    def test_verified(self):
+        """
+        if user verified and we don't redirect
+        """
+        request = Mock()
+        request.session = {}
+        request.user = Mock()
+        request.path = 'subjects'
+        request.user.is_authenticated = True
+        request.user.is_verified = lambda: True
+        result = self.middleware(request)
+        self.assertEqual(result, NOT_REDIRECTED)
+
+    def test_not_verified(self):
+        """
+        if user not verified and not in 2fa section, we redirect to 2fa section
+        """
+        request = Mock()
+        request.session = {}
+        request.user = Mock()
+        request.path = 'subjects'
+        request.user.is_authenticated = True
+        request.user.is_verified = lambda: False
+        result = self.middleware(request)
+        self.assertTrue(isinstance(result, HttpResponseRedirect))
+        self.assertEqual(result.url, '/account/two_factor/')
+
+    def test_not_verified_2fa_section(self):
+        """
+        if user not verified but in 2fa section, we don't redirect
+        """
+        request = Mock()
+        request.session = {}
+        request.user = Mock()
+        request.path = 'two_factor'
+        request.user.is_authenticated = True
+        request.user.is_verified = lambda: False
+        result = self.middleware(request)
+        self.assertEqual(result, NOT_REDIRECTED)