diff --git a/readme.md b/readme.md
index ccf5b24c9408192a70bef30efb01cc3f952f3108..22d11dd3d5f75b4968213ae977ea8759f98d8cf0 100644
--- a/readme.md
+++ b/readme.md
@@ -187,6 +187,13 @@ SHELL=/bin/bash
 
 ## Operations
 
+### Disable two steps authentication for a specific user
+
+
+```
+./manage.py two_factor_disable ${USERNAME}
+```
+
 ### Public holidays
 
 to import public holidays run:
diff --git a/requirements.txt b/requirements.txt
index 0dcc0503db9fadbba8cf9f7f203abd80d3926b62..fa5a7c14be038ab020a18cf2c7e4201737d76b11 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -7,3 +7,5 @@ lxml==3.7.3
 python-docx==0.8.6
 django-cleanup==0.4.2
 django_cron==0.5.0
+django-two-factor-auth==1.6.1
+nexmo
\ No newline at end of file
diff --git a/smash/smash/local_settings.py.template b/smash/smash/local_settings.py.template
index a2411b28e1d8c80401b5741a608faeccdedaf80e..bb8abb8c205e9b027f8af35341958a1cacc28274 100644
--- a/smash/smash/local_settings.py.template
+++ b/smash/smash/local_settings.py.template
@@ -39,3 +39,7 @@ STATIC_ROOT = '/tmp/static'  # Warning! `/tmp` directory can be flushed in any m
 MEDIA_ROOT = '/tmp/media'  # Warning! `/tmp` directory can be flushed in any moment; use a persistent one, e.g. ~/tmp/media
 
 STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
+
+NEXMO_API_KEY = 'API_KEY'
+NEXMO_API_SECRET = 'API_SECRET'
+NEXMO_DEFAULT_FROM = 'Scheduling'  # the sender of the message (phone number or text)
diff --git a/smash/smash/settings.py b/smash/smash/settings.py
index 12e9ac3d4f1c53eeffaa2ca17162c4de3dc9c529..fbdd6e22c2d3175ec692b63332269d03b3ba4e29 100644
--- a/smash/smash/settings.py
+++ b/smash/smash/settings.py
@@ -14,7 +14,7 @@ import os
 
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
+PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
 # Quick-start development settings - unsuitable for production
 # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
 
@@ -31,8 +31,13 @@ INSTALLED_APPS = [
     'django.contrib.staticfiles',
     'django_cleanup',
     'django_cron',
-    'debug_toolbar',
-    'web'
+    'django_otp',
+    'django_otp.plugins.otp_static',
+    'django_otp.plugins.otp_totp',
+    'two_factor',
+    'web',
+
+    'debug_toolbar'
 ]
 
 MIDDLEWARE = [
@@ -42,6 +47,7 @@ MIDDLEWARE = [
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django_otp.middleware.OTPMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 ]
@@ -51,7 +57,7 @@ ROOT_URLCONF = 'smash.urls'
 TEMPLATES = [
     {
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
+        'DIRS': [os.path.join(PROJECT_PATH, '../web', 'templates')],
         'APP_DIRS': True,
         'OPTIONS': {
             'context_processors': [
@@ -112,7 +118,9 @@ STATIC_URL = '/static/'
 MEDIA_URL = '/media/'
 
 # Used for @login_required ecosystem
-LOGIN_URL = '/login'
-LOGOUT_URL = '/logout'
+# LOGIN_URL = '/login'
+LOGIN_URL = 'two_factor:login'
+LOGIN_REDIRECT_URL = 'web.views.appointments'
+LOGOUT_REDIRECT_URL = 'web.views.appointments'
 
 from local_settings import *
diff --git a/smash/smash/urls.py b/smash/smash/urls.py
index e2a8cc8f902b3a586d0b958bbb56e116b4b1a799..bf0f4e881de1772f73ad99303e29e04b9950beb7 100644
--- a/smash/smash/urls.py
+++ b/smash/smash/urls.py
@@ -14,16 +14,17 @@ Including another URLconf
     2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
 """
 
-from django.conf.urls import url, include
-from django.contrib import admin
 from django.conf import settings
+from django.conf.urls import url, include
 from django.conf.urls.static import static
+from django.contrib import admin
 
-import web.urls
-import web.api_urls
+from web import api_urls
+from web import urls
 
 urlpatterns = [
-    url(r'^admin/', admin.site.urls),
-    url(r'', include(web.urls)),
-    url(r'^api/', include(web.api_urls))
-] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+                  url(r'^admin/', admin.site.urls),
+                  url(r'', include(urls)),
+                  url(r'^api/', include(api_urls)),
+                  url(r'', include('two_factor.urls', 'two_factor'))
+              ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/smash/web/models/worker.py b/smash/web/models/worker.py
index fe6fc96e2e3e07f3290b7010c96c20a6d215b5fe..e962487c74522ec5a5ccd94e7373772e14e6f51e 100644
--- a/smash/web/models/worker.py
+++ b/smash/web/models/worker.py
@@ -1,7 +1,7 @@
 # coding=utf-8
 import datetime
 
-from django.contrib.auth.models import User
+from django.contrib.auth.models import User, AnonymousUser
 from django.db import models
 
 
@@ -68,6 +68,8 @@ class Worker(models.Model):
                 return None
         elif isinstance(the_user, Worker):
             return the_user
+        elif isinstance(the_user, AnonymousUser):
+            return None
         elif the_user is not None:
             raise TypeError("Unknown class type: " + the_user.__class__.__name__)
         else:
diff --git a/smash/web/nexmo_gateway.py b/smash/web/nexmo_gateway.py
new file mode 100644
index 0000000000000000000000000000000000000000..0515c732b1ce3a96e8a414eb9bc6fb712054efcd
--- /dev/null
+++ b/smash/web/nexmo_gateway.py
@@ -0,0 +1,34 @@
+import nexmo
+from django.conf import settings
+
+
+class Nexmo:
+    """
+    Gateway for sending text messages and making phone calls using Nexmo_.
+
+    All you need is your Nexmo Account API and Secret, as shown in your Nexmo
+    account dashboard.
+
+    ``NEXMO_API_KEY``
+      Should be set to your account's API Key.
+
+    ``NEXMO_API_SECRET``
+      Should be set to your account's secret.
+
+    ``NEXMO_DEFAULT_FROM``
+      Should be set to a phone number or name.
+
+    .. _Nexmo: http://www.nexmo.com/
+    """
+
+    def __init__(self):
+        self.client = nexmo.Client(key=getattr(settings, 'NEXMO_API_KEY'), secret=getattr(settings, 'NEXMO_API_SECRET'))
+        self.default_from = getattr(settings, 'NEXMO_DEFAULT_FROM')
+
+    def make_call(self, device, token):
+        pass
+
+    def send_sms(self, device, token):
+        body = 'Your authentication token is %s' % token
+        phone_number = device.number.as_e164
+        self.client.send_message({'to': phone_number, 'from': self.default_from, 'text': body})
diff --git a/smash/web/templates/_base.html b/smash/web/templates/_base.html
index b561c6457d753953f82aee5d3b413f0f26bf94a4..69834e355309c677d548c53b4ab70c5af80cdcae 100644
--- a/smash/web/templates/_base.html
+++ b/smash/web/templates/_base.html
@@ -194,9 +194,13 @@ desired effect
                                   <a href="#" class="btn btn-default btn-flat"><i class="fa fa-user"></i> Profile</a>
                                 </div>-->
                                 <div class="pull-right">
-                                    <a href="{% url 'web.views.logout' %}" class="btn btn-default btn-flat"><i
+                                    <a href="{% url 'logout' %}" class="btn btn-default btn-flat"><i
                                             class="fa fa-sign-out"></i> Sign out</a>
                                 </div>
+                                <div class="pull-left">
+                                    <a href="{% url 'two_factor:profile' %}" class="btn btn-default btn-flat"><i
+                                            class="fa fa-lock"></i> Security</a>
+                                </div>
                             </li>
                         </ul>
                     </li>
diff --git a/smash/web/templates/appointments/index.html b/smash/web/templates/appointments/index.html
index 6e14a48c9ef9ff4c68afcb9ac3275b5f4628e36b..2915da109d4e7ba085f71f7adc38394f439f9a83 100644
--- a/smash/web/templates/appointments/index.html
+++ b/smash/web/templates/appointments/index.html
@@ -118,7 +118,7 @@
                 eventRender: function (event, element) {
                     var content = "<ul>";
                     if (event.phone_number) {
-                        content += '<li>Phone number: ' + event.phone_number + '</li>'
+                        content += '<li>Phone numbers: ' + event.phone_number + '</li>'
                     }
                     if (event.screening_number) {
                         content += '<li>Screening number: ' + event.screening_number + '</li>'
diff --git a/smash/web/templates/login.html b/smash/web/templates/login.html
index e02c5705f25549909a6de2ea5a2968915cdec322..e3ba68154ec303856c01c9e10ccad9f7671528b6 100644
--- a/smash/web/templates/login.html
+++ b/smash/web/templates/login.html
@@ -50,60 +50,62 @@
             <h5 class="login-logo-h5">(Smart Scheduling)</h5>
         </div>
         <!-- /.login-logo -->
+        {% block content %}
+            {% if state == "logout" %}
+                <div class="callout callout-info">
+                    <h4>Success!</h4>
 
-        {% if state == "logout" %}
-            <div class="callout callout-info">
-                <h4>Success!</h4>
-
-                <p>You have logged out of the Scheduling System</p>
-            </div>
-        {% elif state == "logout_failed" %}
-            <div class="callout callout-danger">
-                <h4>Error!</h4>
-
-                <p>You cannot log out, if you are not logged in!</p>
-            </div>
-        {% elif state == "login_failed" %}
-            <div class="callout callout-danger">
-                <h4>Error!</h4>
-
-                <p>Username does not exist, or the password is incorrect!</p>
-            </div>
-        {% else %}
-            <hr/>
-        {% endif %}
-
-        <p class="login-box-msg">Please sign in</p>
-
-        <form action="{% url 'web.views.login' %}" method="post">
-            {% csrf_token %}
-            {% if next %}
-                <input type="hidden" name="next" value="{{ next }}"/>
+                    <p>You have logged out of the Scheduling System</p>
+                </div>
+            {% elif state == "logout_failed" %}
+                <div class="callout callout-danger">
+                    <h4>Error!</h4>
+
+                    <p>You cannot log out, if you are not logged in!</p>
+                </div>
+            {% elif state == "login_failed" %}
+                <div class="callout callout-danger">
+                    <h4>Error!</h4>
+
+                    <p>Username does not exist, or the password is incorrect!</p>
+                </div>
+            {% else %}
+                <hr/>
             {% endif %}
 
-            <div class="form-group has-feedback">
-                <input type="text" name="username" class="form-control" placeholder="Login">
-                <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
-            </div>
-            <div class="form-group has-feedback">
-                <input type="password" name="password" class="form-control" placeholder="Password">
-                <span class="glyphicon glyphicon-lock form-control-feedback"></span>
-            </div>
-            <div class="row">
-                <div class="col-xs-8">
-                    <div class="checkbox icheck">
-                        <label>
-                            <input type="checkbox">&nbsp;Remember Me
-                        </label>
-                    </div>
+            <p class="login-box-msg">Please sign in</p>
+
+            <form action="{% url 'web.views.login' %}" method="post">
+                {% csrf_token %}
+                {% if next %}
+                    <input type="hidden" name="next" value="{{ next }}"/>
+                {% endif %}
+
+                <div class="form-group has-feedback">
+                    <input type="text" name="username" class="form-control" placeholder="Login">
+                    <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
+                </div>
+                <div class="form-group has-feedback">
+                    <input type="password" name="password" class="form-control" placeholder="Password">
+                    <span class="glyphicon glyphicon-lock form-control-feedback"></span>
                 </div>
-                <!-- /.col -->
-                <div class="col-xs-4">
-                    <button type="submit" class="btn btn-primary btn-block btn-flat">Sign In</button>
+                <div class="row">
+                    <div class="col-xs-8">
+                        <div class="checkbox icheck">
+                            <label>
+                                <input type="checkbox">&nbsp;Remember Me
+                            </label>
+                        </div>
+                    </div>
+                    <!-- /.col -->
+                    <div class="col-xs-4">
+                        <button type="submit" class="btn btn-primary btn-block btn-flat">Sign In</button>
+                    </div>
+                    <!-- /.col -->
                 </div>
-                <!-- /.col -->
-            </div>
-        </form>
+            </form>
+        {% endblock content %}
+
 
         <hr/>
 
diff --git a/smash/web/templates/two_factor/_base.html b/smash/web/templates/two_factor/_base.html
new file mode 100644
index 0000000000000000000000000000000000000000..97f9798d0998abf247c9137aa315e0bfc25f070a
--- /dev/null
+++ b/smash/web/templates/two_factor/_base.html
@@ -0,0 +1,6 @@
+{% extends "_base.html" %}
+
+{% block maincontent %}
+    {% block content %}
+    {% endblock content %}
+{% endblock maincontent %}
\ No newline at end of file
diff --git a/smash/web/templates/two_factor/core/login.html b/smash/web/templates/two_factor/core/login.html
new file mode 100644
index 0000000000000000000000000000000000000000..318bedb1824713dd1d2c33ba6d0def425f32c7ce
--- /dev/null
+++ b/smash/web/templates/two_factor/core/login.html
@@ -0,0 +1,56 @@
+{% extends "login.html" %}
+{% load i18n two_factor %}
+
+{% block content %}
+
+
+
+
+
+
+    {% if wizard.steps.current == 'auth' %}
+        <p class="login-box-msg">Please sign in</p>
+    {% elif wizard.steps.current == 'token' %}
+        {% if device.method == 'call' %}
+            <p class="login-box-msg">{% blocktrans %}We are calling your phone right now, please enter the
+                digits you hear.{% endblocktrans %}</p>
+        {% elif device.method == 'sms' %}
+            <p class="login-box-msg">{% blocktrans %}We sent you a text message, please enter the tokens we
+                sent.{% endblocktrans %}</p>
+        {% else %}
+            <p class="login-box-msg">{% blocktrans %}Please enter the tokens generated by your token
+                generator.{% endblocktrans %}</p>
+        {% endif %}
+    {% elif wizard.steps.current == 'backup' %}
+        <p class="login-box-msg">{% blocktrans %}Use this form for entering backup tokens for logging in.
+            These tokens have been generated for you to print and keep safe. Please
+            enter one of these backup tokens to login to your account.{% endblocktrans %}</p>
+    {% endif %}
+
+    <form action="" method="post">{% csrf_token %}
+        {% include "two_factor/_wizard_forms.html" %}
+
+        {# hidden submit button to enable [enter] key #}
+        <div style="margin-left: -9999px"><input type="submit" value=""/></div>
+
+        {% if other_devices %}
+            <p>{% trans "Or, alternatively, use one of your backup phones:" %}</p>
+            <p>
+                {% for other in other_devices %}
+                    <button name="challenge_device" value="{{ other.persistent_id }}"
+                            class="btn btn-default btn-block" type="submit">
+                        {{ other|device_action }}
+                    </button>
+                {% endfor %}</p>
+        {% endif %}
+        {% if backup_tokens %}
+            <p>{% trans "As a last resort, you can use a backup token:" %}</p>
+            <p>
+                <button name="wizard_goto_step" type="submit" value="backup"
+                        class="btn btn-default btn-block">{% trans "Use Backup Token" %}</button>
+            </p>
+        {% endif %}
+
+        {% include "two_factor/_wizard_actions.html" %}
+    </form>
+{% endblock %}
\ No newline at end of file
diff --git a/smash/web/templates/two_factor/profile/profile.html b/smash/web/templates/two_factor/profile/profile.html
new file mode 100644
index 0000000000000000000000000000000000000000..bbfeda8d13dd5aac4a5ebb187f2430633816c10f
--- /dev/null
+++ b/smash/web/templates/two_factor/profile/profile.html
@@ -0,0 +1,59 @@
+{% extends "two_factor/_base.html" %}
+{% load i18n two_factor %}
+
+{% block content %}
+    <h1>{% block title %}{% trans "Account Security" %}{% endblock %}</h1>
+
+    {% if default_device %}
+        {% if default_device_type == 'TOTPDevice' %}
+            <p>{% trans "Tokens will be generated by your token generator." %}</p>
+        {% elif default_device_type == 'PhoneDevice' %}
+            <p>{% blocktrans with primary=default_device|device_action %}Primary method:
+                {{ primary }}{% endblocktrans %}</p>
+        {% elif default_device_type == 'RemoteYubikeyDevice' %}
+            <p>{% blocktrans %}Tokens will be generated by your YubiKey.{% endblocktrans %}</p>
+        {% endif %}
+
+        <h2>{% trans "Backup Phone Numbers" %}</h2>
+        <p>{% blocktrans %}If your primary method is not available, we are able to
+            send backup tokens to the phone numbers listed below.{% endblocktrans %}</p>
+        <ul>
+            {% for phone in backup_phones %}
+                <li>
+                    {{ phone|device_action }}
+                    <form method="post" action="{% url 'two_factor:phone_delete' phone.id %}"
+                          onsubmit="return confirm('Are you sure?')">
+                        {% csrf_token %}
+                        <button class="btn btn-xs btn-warning"
+                                type="submit">{% trans "Unregister" %}</button>
+                    </form>
+                </li>
+            {% endfor %}
+        </ul>
+        {% if available_phone_methods %}
+            <p><a href="{% url 'two_factor:phone_create' %}"
+                  class="btn btn-info">{% trans "Add Phone Number" %}</a></p>
+        {% endif %}
+
+        <h2>{% trans "Backup Tokens" %}</h2>
+        <p>
+            {% blocktrans %}If you don't have any device with you, you can access
+                your account using backup tokens.{% endblocktrans %}
+            {% blocktrans count counter=backup_tokens %}
+                You have only one backup token remaining.
+            {% plural %}
+                You have {{ counter }} backup tokens remaining.
+            {% endblocktrans %}
+        </p>
+        <p><a href="{% url 'two_factor:backup_tokens' %}"
+              class="btn btn-info">{% trans "Show Codes" %}</a></p>
+
+    {% else %}
+        <p>{% blocktrans %}Two-factor authentication is not enabled for your
+            account. Enable two-factor authentication for enhanced account
+            security.{% endblocktrans %}</p>
+        <p><a href="{% url 'two_factor:setup' %}" class="btn btn-primary">
+            {% trans "Enable Two-Factor Authentication" %}</a>
+        </p>
+    {% endif %}
+{% endblock %}
\ No newline at end of file
diff --git a/smash/web/tests/test_view_login.py b/smash/web/tests/test_view_login.py
index 4e662d9de2085340c9998676081c7f4dcece35f2..f3fa9b05d3152c6fc7a6542e03bbaf4a8937c0d1 100644
--- a/smash/web/tests/test_view_login.py
+++ b/smash/web/tests/test_view_login.py
@@ -1,4 +1,5 @@
 # coding=utf-8
+from django.conf import settings
 from django.contrib import auth as django_auth
 from django.test import Client
 from django.test import TestCase
@@ -14,29 +15,31 @@ class TestLoginView(TestCase):
         user = create_user()
         password = 'top_secret'
         username = user.username
-        login_url = reverse('web.views.login')
+        login_url = reverse(settings.LOGIN_URL)
         self.assertFalse(django_auth.get_user(self.client).is_authenticated())
-        response = self.client.post(login_url, data={'username': username, 'password': password}, follow=True)
+        form_data = {'auth-username': username, 'auth-password': password, 'login_view-current_step': 'auth'}
+        response = self.client.post(login_url, data=form_data, follow=True)
         self.assertEqual(200, response.status_code)
         self.assertTrue(django_auth.get_user(self.client).is_authenticated())
         worker = Worker.get_by_user(user)
         self.assertIsNotNone(worker)
         worker.last_name = 'Grouès'
         worker.save()
-        response = self.client.post(login_url, data={'username': username, 'password': password}, follow=True)
+        response = self.client.post(login_url, data=form_data, follow=True)
         self.assertEqual(200, response.status_code)
 
     def test_login_failed(self):
         self.client = Client()
         user = create_user()
         username = user.username
-        login_url = reverse('web.views.login')
-        response = self.client.post(login_url, data={'username': username, 'password': 'wrong_password'}, follow=False)
-        self.assertEqual(302, response.status_code)
-        self.assertEqual('/login?error=login_failed', response.url)
+        login_url = reverse(settings.LOGIN_URL)
+        response = self.client.post(login_url, data={'auth-username': username, 'auth-password': 'wrong-password',
+                                                     'login_view-current_step': 'auth'}, follow=False)
+        self.assertContains(response, 'Please enter a correct')
+        self.assertContains(response, 'and password.')
         self.assertFalse(django_auth.get_user(self.client).is_authenticated())
 
     def test_logout(self):
         self.test_login()
-        self.client.get(reverse('web.views.logout'))
+        self.client.get(reverse('logout'))
         self.assertFalse(django_auth.get_user(self.client).is_authenticated())
diff --git a/smash/web/urls.py b/smash/web/urls.py
index 137dd4f057f70f914fdcf71b684b27271fce9e15..9c50298a34d5ce746718a97beb8d5c379615048b 100644
--- a/smash/web/urls.py
+++ b/smash/web/urls.py
@@ -17,12 +17,22 @@ from django.conf import settings
 from django.conf.urls import include
 from django.conf.urls import url
 from django.contrib.auth.decorators import login_required
+from django.contrib.auth.views import logout
+from django.views.defaults import page_not_found
 from django.views.generic import TemplateView
 
 from web import views
 
 urlpatterns = [
 
+    # make sure that users cannot disable two factors authentication
+
+    url(
+        r'^account/two_factor/disable/$',
+        page_not_found,
+        {'exception': Exception('Not Found')}
+    ),
+
     ####################
     #   APPOINTMENTS   #
     ####################
@@ -118,7 +128,8 @@ urlpatterns = [
     ####################
 
 
-    url(r'^daily_planning$', login_required(TemplateView.as_view(template_name='daily_planning.html')), name='web.views.daily_planning'),
+    url(r'^daily_planning$', login_required(TemplateView.as_view(template_name='daily_planning.html')),
+        name='web.views.daily_planning'),
 
     ####################
     #     LANGUAGES    #
@@ -154,8 +165,9 @@ urlpatterns = [
     #       AUTH       #
     ####################
 
-    url(r'^login$', views.auth.login, name='web.views.login'),
-    url(r'^logout$', views.auth.logout, name='web.views.logout'),
+    # url(r'^login$', views.auth.login, name='web.views.login'),
+    # url(r'^logout$', views.auth.logout, name='web.views.logout'),
+    url(r'^logout$', logout, name='logout'),
 
     url(r'^$', views.index, name='web.views.index')
 ]
diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py
index 4322cb370c651c5e613bf6f708f68a559aa7c315..49fc1dceaf3ea3695f54ad8066803bc41dab7d9a 100644
--- a/smash/web/views/__init__.py
+++ b/smash/web/views/__init__.py
@@ -1,5 +1,5 @@
 # coding=utf-8
-
+from django.conf import settings
 from django.contrib.auth.decorators import login_required
 from django.shortcuts import redirect, render
 from django.views.generic.base import ContextMixin
@@ -16,7 +16,7 @@ handler400 = 'web.views.e400_bad_request'
 def index(request):
     if request.user.is_authenticated():
         return redirect('web.views.appointments')
-    return redirect('web.views.login')
+    return redirect(getattr(settings, "LOGIN_URL"))
 
 
 def e404_page_not_found(request, context=None):
diff --git a/smash/web/views/auth.py b/smash/web/views/auth.py
index 2e095773c321d1a6b201d3c50d582f36e37e5e99..1a293f4ae4c379610fbf69b959f93dc79dcf4060 100644
--- a/smash/web/views/auth.py
+++ b/smash/web/views/auth.py
@@ -1,8 +1,11 @@
 # coding=utf-8
+from django.conf import settings
 from django.shortcuts import redirect, render
 
 from ..auth import do_login, do_logout
 
+login_url = getattr(settings, "LOGIN_URL")
+
 
 def login(request):
     context = {
@@ -22,9 +25,9 @@ def login(request):
                 # FIXME: risk of phishing attacks
                 #  see https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet
             else:
-                return redirect('web.views.appointments')
+                return redirect(login_url)
         else:
-            response = redirect('web.views.login')
+            response = redirect(login_url)
             response['Location'] += "?error={}".format(message)
             return response
     return render(request, "login.html", context)
@@ -32,6 +35,6 @@ def login(request):
 
 def logout(request):
     state, message = do_logout(request)
-    response = redirect('web.views.login')
+    response = redirect(login_url)
     response['Location'] += "?error={}".format(message)
     return response