Added 2FA with U2F keys.

This commit is contained in:
Jan Böhmer 2019-12-29 13:35:30 +01:00
parent 47fa8b04e5
commit 069293a843
18 changed files with 512 additions and 157 deletions

View file

@ -16,6 +16,10 @@
<a class="nav-link" id="backup-tab" data-toggle="tab" href="#tfa-backup" role="tab"
aria-controls="profile" aria-selected="false">{% trans %}tfa.settings.bakup.tab{% endtrans %}</a>
</li>
<li class="nav-item">
<a class="nav-link" id="u2f-tab" data-toggle="tab" href="#tfa-u2f" role="tab"
aria-controls="profile" aria-selected="false">{% trans %}tfa.settings.u2f.tab{% endtrans %}</a>
</li>
</ul>
<div class="tab-content mt-3 mb-3" id="tfa-tabs-content">
<div class="tab-pane fade show active" id="tfa-google" role="tabpanel" aria-labelledby="google-tab">
@ -90,6 +94,37 @@
{% endif %}
</div>
<div class="tab-pane fade" id="tfa-u2f" role="tabpanel" aria-labelledby="u2f-tab">
<p>{% trans %}tfa_u2f.explanation{% endtrans %}</p>
{% if user.u2FKeys is not empty %}
<b>{% trans %}tfa_u2f.table_caption{% endtrans %}:</b>
<table class="table table-striped table-bordered table-sm mt-2">
<thead>
<tr>
<th>#</th>
<th>{% trans %}tfa_u2f.keys.name{% endtrans %}</th>
<th>{% trans %}tfa_u2f.keys.added_date{% endtrans %}</th>
</tr>
</thead>
<tbody>
{% for key in user.u2FKeys %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ key.name }}</td>
<td>{{ key.addedDate | format_datetime }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p><b>{% trans %}tfa_u2f.no_keys_registered{% endtrans %}</b></p>
{% endif %}
<a href="{{ url('club_base_register_u2f') }}" class="btn btn-success"><i class="fas fa-plus-square fa-fw"></i> {% trans %}tfa_u2f.add_new_key{% endtrans %}</a>
</div>
</div>

View file

@ -123,6 +123,10 @@
<script src="{{ preload(asset(js), {as: 'script'}) }}"></script>
{% endfor %}
{% for js in encore_entry_js_files('ru2ftwofactor') %}
<script src="{{ preload(asset(js), {as: 'script'}) }}"></script>
{% endfor %}
{% endblock %}
{% block scripts %}

View file

@ -0,0 +1,58 @@
{% extends "main_card.html.twig" %}
{% block title %}{% trans %}tfa.check.title{% endtrans %}{% endblock %}
{% block card_title %}<i class="fas fa-shield-alt"></i> {% trans %}tfa.check.title{% endtrans %}{% endblock %}
{% block content %}
{% if authenticationError %}
<div class="alert alert-danger" role="alert">
<strong>{{ authenticationError|trans(authenticationErrorData, 'SchebTwoFactorBundle') }}}</strong>
</div>
{% endif %}
{{ parent() }}
{% endblock %}
{% block card_content %}
<ul class="nav nav-pills mb-4">
{% for provider in availableTwoFactorProviders %}
<li class="nav-item">
<a class="nav-link {% if provider == twoFactorProvider %}active{% endif %}"
href="{{ path("2fa_login", {"preferProvider": provider}) }}">{{ 'tfa.provider.'~provider | trans }}</a>
</li>
{% endfor %}
</ul>
{# Display current two-factor provider #}
<form class="form form-horizontal" action="{{ path("2fa_login_check") }}" method="post" {% block form_attributes %}{% endblock %}>
{% block form %}
{% endblock %}
{% if displayTrustedOption %}
<div class="form-group row mt-3">
<div class="offset-3">
<div class="custom-checkbox custom-control ml-2">
<input id="_trusted" class="custom-control-input" type="checkbox" name="{{ trustedParameterName }}" />
<label class="custom-control-label" for="_trusted">{% trans %}tfa.code.trusted_pc{% endtrans %}</label>
</div>
</div>
</div>
{% endif %}
{% if isCsrfProtectionEnabled %}
<input type="hidden" name="{{ csrfParameterName }}" value="{{ csrf_token(csrfTokenId) }}">
{% endif %}
{% block submit_btn %}
<div class="form-group-row">
<div class="offset-3">
<button type="submit" class="btn btn-primary" value="{{ "login"|trans({}, 'SchebTwoFactorBundle') }}">{% trans %}login.btn{% endtrans %}</button>
<a class="ml-2" href="{{ logoutPath }}">{% trans %}user.logout{% endtrans %}</a>
</div>
</div>
{% endblock %}
</form>
{% endblock %}

View file

@ -1,61 +1,14 @@
{% extends "main_card.html.twig" %}
{% extends "security/2fa_base_form.html.twig" %}
{% block title %}{% trans %}tfa.check.title{% endtrans %}{% endblock %}
{% block card_title %}<i class="fas fa-shield-alt"></i> {% trans %}tfa.check.title{% endtrans %}{% endblock %}
{% block content %}
{% if authenticationError %}
<div class="alert alert-danger" role="alert">
<strong>{{ authenticationError|trans(authenticationErrorData, 'SchebTwoFactorBundle') }}}</strong>
{% block form %}
<div class="form-group row">
<label for="_auth_code" class="col-form-label col-3">{% trans %}tfa.check.code.label{% endtrans %}</label>
<div class="col-9">
<input id="_auth_code" class="form-control" type="text" autocomplete="off" name="{{ authCodeParameterName }}" autofocus />
<small id="passwordHelpBlock" class="form-text text-muted">
{% trans %}tfa.check.code.help{% endtrans %}
</small>
</div>
{% endif %}
{{ parent() }}
{% endblock %}
{% block card_content %}
<ul class="nav nav-pills mb-4">
{% for provider in availableTwoFactorProviders %}
<li class="nav-item">
<a class="nav-link {% if provider == twoFactorProvider %}active{% endif %}"
href="{{ path("2fa_login", {"preferProvider": provider}) }}">{{ 'tfa.provider.'~provider | trans }}</a>
</li>
{% endfor %}
</ul>
{# Display current two-factor provider #}
<form class="form form-horizontal" action="{{ path("2fa_login_check") }}" method="post">
<div class="form-group row">
<label for="_auth_code" class="col-form-label col-3">{% trans %}tfa.check.code.label{% endtrans %}</label>
<div class="col-9">
<input id="_auth_code" class="form-control" type="text" autocomplete="off" name="{{ authCodeParameterName }}" autofocus />
<small id="passwordHelpBlock" class="form-text text-muted">
{% trans %}tfa.check.code.help{% endtrans %}
</small>
</div>
</div>
{% if displayTrustedOption %}
<div class="form-group row mt-3">
<div class="offset-3">
<div class="custom-checkbox custom-control ml-2">
<input id="_trusted" class="custom-control-input" type="checkbox" name="{{ trustedParameterName }}" />
<label class="custom-control-label" for="_trusted">{% trans %}tfa.code.trusted_pc{% endtrans %}</label>
</div>
</div>
</div>
{% endif %}
{% if isCsrfProtectionEnabled %}
<input type="hidden" name="{{ csrfParameterName }}" value="{{ csrf_token(csrfTokenId) }}">
{% endif %}
<div class="form-group-row">
<div class="offset-3">
<button type="submit" class="btn btn-primary" value="{{ "login"|trans({}, 'SchebTwoFactorBundle') }}">{% trans %}login.btn{% endtrans %}</button>
<a class="ml-2" href="{{ logoutPath }}">{% trans %}user.logout{% endtrans %}</a>
</div>
</div>
</form>
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends "security/2fa_base_form.html.twig" %}
{% block form_attributes %}id="u2fForm" data-action="auth" data-request='{{ authenticationData|raw }}'{% endblock %}
{% block form %}
{% if not app.request.secure %}
<p class="text-warning"><b><i class="fas fa-exclamation-triangle fa-fw"></i> {% trans %}tfa_u2f.http_warning{% endtrans %}</b></p>
{% endif %}
<div id="u2fpressbutton" style="display: none;" class="h4 text-center">{{ 'r_u2f_two_factor.pressbutton'|trans }}</div>
<div id="u2fError"></div>
<p class="widget"><input id="_auth_code" type="hidden" autocomplete="off" name="_auth_code" /></p>
{% endblock %}
{% block submit_btn %}
{% endblock %}

View file

@ -0,0 +1,28 @@
{% extends "main_card.html.twig" %}
{% block card_title %}<i class="fas fa-plus-square fa-fw"></i> {% trans %}tfa_u2f.add_key.title{% endtrans %}{% endblock %}
{% block card_content %}
<p>{% trans %}tfa_u2f.explanation{% endtrans %}</p>
<p><b>{% trans %}tfa_u2f.add_key.backup_hint{% endtrans %}</b></p>
{% if not app.request.secure %}
<p class="text-warning"><b><i class="fas fa-exclamation-triangle fa-fw"></i> {% trans %}tfa_u2f.http_warning{% endtrans %}</b></p>
{% endif %}
<form method="post" class="form" action="{{ path('club_base_register_u2f') }}" id="u2fForm" data-action="reg" data-request='{{ registrationRequest|raw }}'>
<div id="u2fkeyname" class="form-group row">
<div class="col-9">
<input type="text" class="form-control " name="keyName" id="keyName" placeholder="{{ 'r_u2f_two_factor.name'|trans }}"/>
</div>
<div class="col-3">
<button type="button" class="btn btn-success" onclick="u2fauth.register()">{% trans %}tfa_u2f.add_key.add_button{% endtrans %}</button>
</div>
</div>
<div id="u2fpressbutton" style="display: none;" class="text-center h4">{{ 'r_u2f_two_factor.pressbutton'|trans }}</div>
<input type="hidden" name="_auth_code" id="_auth_code" />
<div id="u2fError" style="display: none;" class="text-center h4"></div>
</form>
<a href="{{ url('user_settings') }}">{% trans %}tfa_u2f.add_key.back_to_settings{% endtrans %}</a>
{% endblock %}