Skip to content

Commit

Permalink
SIO-2038 Basic support for 2FA.
Browse files Browse the repository at this point in the history
Change-Id: Ied39f660dd0ba6a84b8a9249e0489beecf2513fe
  • Loading branch information
mrowqa committed Mar 15, 2018
1 parent 7c0e0a4 commit de2d573
Show file tree
Hide file tree
Showing 16 changed files with 292 additions and 75 deletions.
4 changes: 4 additions & 0 deletions oioioi/base/static/scss/_layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ $oioioi-narrow-input-max-width: 300px !default;
padding-left: 0;
}

.padding-bottom-md {
padding-bottom: 1em;
}

.h-scrollable {
overflow-x: auto;
}
Expand Down
5 changes: 3 additions & 2 deletions oioioi/base/templates/ingredients/navbar-user.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
<li class="navbar-form">
<form id="navbar-login" class="navbar-login" action="{% url 'login' %}" method="post">
{% csrf_token %}
<input name="login_view-current_step" type="hidden" value="auth">
<div class="form-group">
<input type="text" name="username" class="form-control" placeholder="{% trans "Login" %}">
<input type="text" name="auth-username" class="form-control" placeholder="{% trans "Login" %}">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="{% trans "Password" %}">
<input type="password" name="auth-password" class="form-control" placeholder="{% trans "Password" %}">
</div>
<a role="button" class="btn btn-default" href="{% url 'registration_register' %}">{% trans "Register" %}</a>
<button type="submit" class="btn btn-primary">{% trans "Log in" %}</button>
Expand Down
66 changes: 0 additions & 66 deletions oioioi/base/templates/registration/login.html

This file was deleted.

1 change: 1 addition & 0 deletions oioioi/base/templates/two_factor/_base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "simple-centered.html" %}
9 changes: 9 additions & 0 deletions oioioi/base/templates/two_factor/_base_focus.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends "two_factor/_base.html" %}

{% block body %}
<div class="row padding-bottom-md">
<div class="col-md-8 col-md-offset-2">
{% block content %}{% endblock %}
</div>
</div>
{% endblock %}
24 changes: 24 additions & 0 deletions oioioi/base/templates/two_factor/_wizard_actions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{% load i18n %}

{% comment %}
Our changes:

Moved cancel button to the end, so now using tab key
we iterate over buttons in natural order.
{% endcomment %}

{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit"
value="{{ wizard.steps.prev }}"
class="btn btn-default">{% trans "Back" %}</button>
{% else %}
<button disabled name="" type="button"
class="btn btn-disabled">{% trans "Back" %}</button>
{% endif %}

<button type="submit" class="btn btn-primary">{% trans "Next" %}</button>

{% if cancel_url %}
<a href="{{ cancel_url }}"
class="pull-right btn btn-link">{% trans "Cancel" %}</a>
{% endif %}
4 changes: 4 additions & 0 deletions oioioi/base/templates/two_factor/_wizard_forms.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{{ wizard.management_form }}
<div class="form-horizontal">
{% include "ingredients/form-horizontal.html" with form=wizard.form %}
</div>
73 changes: 73 additions & 0 deletions oioioi/base/templates/two_factor/core/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{% extends "two_factor/_base_focus.html" %}
{% load i18n two_factor %}

{% block content %}
{% comment %}
Our changes:

* Using well for better looking form
* Centered "Log in" heading, also using "Log in" instead of "Login"
* Adding links to password reset and registration
* Removed "Enter your credentials." message (wizard.steps.current == 'auth')
{% endcomment %}

<div class="well">
<div class="form-group">
<div class="text-center">
<h1>{% block title %}{% trans "Log in" %}{% endblock %}</h1>
</div>
</div>

{% if wizard.steps.current == 'token' %}
{% if device.method == 'call' %}
<p>{% blocktrans %}We are calling your phone right now, please enter the
digits you hear.{% endblocktrans %}</p>
{% elif device.method == 'sms' %}
<p>{% blocktrans %}We sent you a text message, please enter the tokens we
sent.{% endblocktrans %}</p>
{% else %}
<p>{% blocktrans %}Please enter the tokens generated by your token
generator.{% endblocktrans %}</p>
{% endif %}
{% elif wizard.steps.current == 'backup' %}
<p>{% 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 %}

{% if wizard.steps.current == 'auth' %}
<div class="form-group">
<p><a href="{% url 'auth_password_reset' %}">{% trans "Forgot password?" %}</a></p>
<p><a href="{% url 'registration_register' %}">{% trans "Want to create an account?" %}</a></p>
</div>
{% endif %}

{% include "two_factor/_wizard_actions.html" %}
</form>
</div>
{% endblock %}
62 changes: 62 additions & 0 deletions oioioi/base/templates/two_factor/core/setup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{% extends "two_factor/_base_focus.html" %}
{% load i18n %}

{% block content %}
{% comment %}
Our changes:

* Centered QR code.
{% endcomment %}

<h1>{% block title %}{% trans "Enable Two-Factor Authentication" %}{% endblock %}</h1>
{% if wizard.steps.current == 'welcome' %}
<p>{% blocktrans %}You are about to take your account security to the
next level. Follow the steps in this wizard to enable two-factor
authentication.{% endblocktrans %}</p>
{% elif wizard.steps.current == 'method' %}
<p>{% blocktrans %}Please select which authentication method you would
like to use.{% endblocktrans %}</p>
{% elif wizard.steps.current == 'generator' %}
<p>{% blocktrans %}To start using a token generator, please use your
smartphone to scan the QR code below. For example, use Google
Authenticator. Then, enter the token generated by the app.
{% endblocktrans %}</p>
<p class="text-center"><img src="{{ QR_URL }}" alt="QR Code" /></p>
{% elif wizard.steps.current == 'sms' %}
<p>{% blocktrans %}Please enter the phone number you wish to receive the
text messages on. This number will be validated in the next step.
{% endblocktrans %}</p>
{% elif wizard.steps.current == 'call' %}
<p>{% blocktrans %}Please enter the phone number you wish to be called on.
This number will be validated in the next step. {% endblocktrans %}</p>
{% elif wizard.steps.current == 'validation' %}
{% if challenge_succeeded %}
{% if device.method == 'call' %}
<p>{% blocktrans %}We are calling your phone right now, please enter the
digits you hear.{% endblocktrans %}</p>
{% elif device.method == 'sms' %}
<p>{% blocktrans %}We sent you a text message, please enter the tokens we
sent.{% endblocktrans %}</p>
{% endif %}
{% else %}
<p class="alert alert-warning" role="alert">{% blocktrans %}We've
encountered an issue with the selected authentication method. Please
go back and verify that you entered your information correctly, try
again, or use a different authentication method instead. If the issue
persists, contact the site administrator.{% endblocktrans %}</p>
{% endif %}
{% elif wizard.steps.current == 'yubikey' %}
<p>{% blocktrans %}To identify and verify your YubiKey, please insert a
token in the field below. Your YubiKey will be linked 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>

{% include "two_factor/_wizard_actions.html" %}
</form>
{% endblock %}
21 changes: 21 additions & 0 deletions oioioi/base/templates/two_factor/profile/disable.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% extends "two_factor/_base_focus.html" %}
{% load i18n %}

{% block content %}
{% comment %}
Our changes:

* Using newer version of this file (1.7.0 or little bit newer).
* Rendering checkbox with our form template.
{% endcomment %}

<h1>{% block title %}{% trans "Disable Two-factor Authentication" %}{% endblock %}</h1>
<p>{% blocktrans %}You are about to disable two-factor authentication. This
weakens your account security, are you sure?{% endblocktrans %}</p>
<form method="post">
{% csrf_token %}
{% include "ingredients/form.html" with form=form %}
<button class="btn btn-danger"
type="submit">{% trans "Disable" %}</button>
</form>
{% endblock %}
70 changes: 70 additions & 0 deletions oioioi/base/templates/two_factor/profile/profile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{% extends "two_factor/_base.html" %}
{% load i18n two_factor %}

{% block content %}
{% comment %}
Our changes:

* Using newer version of this file (1.7.0 or little bit newer)
(this means phone methods are not listed what is what we want since we don't support them)
{% endcomment %}

<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 %}

{% if available_phone_methods %}
<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>
<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>

<h3>{% trans "Disable Two-Factor Authentication" %}</h3>
<p>{% blocktrans %}However we strongly discourage you to do so, you can
also disable two-factor authentication for your account.{% endblocktrans %}</p>
<p><a class="btn btn-default" href="{% url 'two_factor:disable' %}">
{% trans "Disable Two-Factor Authentication" %}</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 %}
5 changes: 4 additions & 1 deletion oioioi/base/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from django.conf.urls import url
from django.conf.urls import url, include

from oioioi.base import admin, views
from oioioi.base.main_page import main_page_view

urlpatterns = [
url(r'', include('two_factor.urls', 'two_factor')),
url(r'^force_error/$', views.force_error_view, name='force_error'),
url(r'^force_permission_denied/$', views.force_permission_denied_view,
name='force_permission_denied'),
Expand All @@ -15,6 +16,8 @@
name='delete_account'),
url(r'^generate_key/$', views.generate_key_view, name='generate_key'),

# don't include without appropriate patching! admincdocs provides its own
# login view which can be used to bypass 2FA.
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/logout/$', views.logout_view),
url(r'^admin/', admin.site.urls),
Expand Down

0 comments on commit de2d573

Please sign in to comment.