1
0
Fork 0
mirror of https://github.com/wallabag/wallabag.git synced 2025-07-22 17:18:37 +00:00

2factor authentication via email

This commit is contained in:
Nicolas Lœuillet 2015-10-13 22:43:15 +02:00
parent cf0ea8f113
commit 2db616b586
11 changed files with 394 additions and 111 deletions

View file

@ -13,6 +13,7 @@ class UserInformationType extends AbstractType
$builder
->add('name', 'text')
->add('email', 'email')
->add('twoFactorAuthentication', 'checkbox', array('required' => false))
->add('save', 'submit')
->remove('username')
->remove('plainPassword')

View file

@ -100,6 +100,14 @@
</div>
</fieldset>
<fieldset class="w500p inline">
<div class="row">
{{ form_label(form.user.twoFactorAuthentication) }}
{{ form_errors(form.user.twoFactorAuthentication) }}
{{ form_widget(form.user.twoFactorAuthentication) }}
</div>
</fieldset>
{{ form_rest(form.user) }}
</form>

View file

@ -132,6 +132,14 @@
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form_widget(form.user.twoFactorAuthentication) }}
{{ form_label(form.user.twoFactorAuthentication) }}
{{ form_errors(form.user.twoFactorAuthentication) }}
</div>
</div>
<div class="hidden">{{ form_rest(form.user) }}</div>
<button class="btn waves-effect waves-light" type="submit" name="action">
{% trans %}Save{% endtrans %}

View file

@ -4,6 +4,8 @@ namespace Wallabag\UserBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
use Scheb\TwoFactorBundle\Model\TrustedComputerInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use JMS\Serializer\Annotation\ExclusionPolicy;
@ -24,7 +26,7 @@ use Wallabag\CoreBundle\Entity\Tag;
* @UniqueEntity("email")
* @UniqueEntity("username")
*/
class User extends BaseUser
class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface
{
/**
* @var int
@ -72,6 +74,22 @@ class User extends BaseUser
*/
protected $tags;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $authCode;
/**
* @var bool Enabled yes/no
* @ORM\Column(type="boolean")
*/
private $twoFactorAuthentication = false;
/**
* @ORM\Column(type="json_array", nullable=true)
*/
private $trusted;
public function __construct()
{
parent::__construct();
@ -201,4 +219,52 @@ class User extends BaseUser
{
return $this->config;
}
/**
* @return bool
*/
public function isTwoFactorAuthentication()
{
return $this->twoFactorAuthentication;
}
/**
* @param bool $twoFactorAuthentication
*/
public function setTwoFactorAuthentication($twoFactorAuthentication)
{
$this->twoFactorAuthentication = $twoFactorAuthentication;
}
public function isEmailAuthEnabled()
{
return $this->twoFactorAuthentication;
}
public function getEmailAuthCode()
{
return $this->authCode;
}
public function setEmailAuthCode($authCode)
{
$this->authCode = $authCode;
}
public function addTrustedComputer($token, \DateTime $validUntil)
{
$this->trusted[$token] = $validUntil->format('r');
}
public function isTrustedComputer($token)
{
if (isset($this->trusted[$token])) {
$now = new \DateTime();
$validUntil = new \DateTime($this->trusted[$token]);
return $now < $validUntil;
}
return false;
}
}

View file

@ -0,0 +1,19 @@
parameters:
wallabag_user.twofactor.email.provider.class: Wallabag\UserBundle\Security\TwoFactor\Email\Helper
wallabag_user.twofactor.email.interactive_login_listener.class: Wallabag\UserBundle\Security\TwoFactor\Email\InteractiveLoginListener
wallabag_user.twofactor.email.request_listener.class: Wallabag\UserBundle\Security\TwoFactor\Email\RequestListener
services:
wallabag_user.twofactor.email.provider:
class: %wallabag_user.twofactor.email.provider.class%
arguments: ['@doctrine.orm.entity_manager', '@mailer']
wallabag_user.twofactor.email.interactive_login_listener:
class: %wallabag_user.twofactor.email.interactive_login_listener.class%
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }
arguments: ['@wallabag_user.twofactor.email.provider']
wallabag_user.twofactor.email.request_listener:
class: %wallabag_user.twofactor.email.request_listener.class%
tags:
- { name: kernel.event_listener, event: kernel.request, method: onCoreRequest, priority: -1 }
arguments: ['@wallabag_user.twofactor.email.provider', '@security.context', '@templating', '@router']

View file

@ -0,0 +1,32 @@
{% extends "WallabagUserBundle::layout.html.twig" %}
{% block fos_user_content %}
<form class="form" action="" method="post">
<fieldset class="w500p center">
{% for flashMessage in app.session.flashbag.get("two_factor") %}
<p class="error">{{ flashMessage|trans }}</p>
{% endfor %}
<div class="row">
<label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
<input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
</div>
{% if useTrustedOption %}
<div class="row">
<input id="_trusted" type="checkbox" name="_trusted" />
<label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label>
</div>
{% endif %}
<div class="row mts txtcenter">
<a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn"><i class="material-icons left"></i> {% trans %}Cancel{% endtrans %}</a>
<button type="submit" name="send">
{{ "scheb_two_factor.login"|trans }}
<i class="mdi-content-send right"></i>
</button>
</div>
</fieldset>
</form>
{% endblock %}

View file

@ -0,0 +1,33 @@
{% extends "WallabagUserBundle::layout.html.twig" %}
{% block fos_user_content %}
<form class="form" action="" method="post">
<div class="card-content">
<div class="row">
{% for flashMessage in app.session.flashbag.get("two_factor") %}
<p class="error">{{ flashMessage|trans }}</p>
{% endfor %}
<div class="input-field col s12">
<label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
<input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
</div>
{% if useTrustedOption %}
<div class="input-field col s12">
<input id="_trusted" type="checkbox" name="_trusted" />
<label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label>
</div>
{% endif %}
</div>
</div>
<div class="card-action center">
<a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn"><i class="material-icons left"></i> {% trans %}Cancel{% endtrans %}</a>
<button class="btn waves-effect waves-light" type="submit" name="send">
{{ "scheb_two_factor.login"|trans }}
<i class="mdi-content-send right"></i>
</button>
</div>
</form>
{% endblock %}