Auth Contrôleurs

Les contrôleurs Auth vous permettent d’effectuer une authentification de base avec :
  • se connecter avec un compte

  • création de compte

  • déconnexion

  • contrôleurs avec l’authentification requise

Création

Dans l’interface d’administration (webtools), activez la partie Controllers, et choisissez de créer un Auth controller :

../_images/speControllerBtn.png
Remplissez ensuite le formulaire :
  • Entrez le nom du contrôleur (BaseAuthController dans ce cas)

../_images/createAuthForm1.png

Le contrôleur généré :

app/controllers/BaseAuthController.php
 1 /**
 2 * Auth Controller BaseAuthController
 3 **/
 4class BaseAuthController extends \Ubiquity\controllers\auth\AuthController{
 5
 6     protected function onConnect($connected) {
 7             $urlParts=$this->getOriginalURL();
 8             USession::set($this->_getUserSessionKey(), $connected);
 9             if(isset($urlParts)){
10                     Startup::forward(implode("/",$urlParts));
11             }else{
12                     //TODO
13                     //Forwarding to the default controller/action
14             }
15     }
16
17     protected function _connect() {
18             if(URequest::isPost()){
19                     $email=URequest::post($this->_getLoginInputName());
20                     $password=URequest::post($this->_getPasswordInputName());
21                     //TODO
22                     //Loading from the database the user corresponding to the parameters
23                     //Checking user creditentials
24                     //Returning the user
25             }
26             return;
27     }
28
29     /**
30      * {@inheritDoc}
31      * @see \Ubiquity\controllers\auth\AuthController::isValidUser()
32      */
33     public function _isValidUser($action=null): bool {
34             return USession::exists($this->_getUserSessionKey());
35     }
36
37     public function _getBaseRoute(): string {
38             return 'BaseAuthController';
39     }
40}

Implémentation de l’authentification

Exemple d’implémentation avec l’interface d’administration : Nous allons ajouter un contrôle d’authentification sur l’interface d’administration.

L’authentification est basée sur la vérification du couple email/password sur le modèle User :

../_images/model-user.png

Modification de BaseAuthController

app/controllers/BaseAuthController.php
 1 /**
 2 * Auth Controller BaseAuthController
 3 **/
 4class BaseAuthController extends \Ubiquity\controllers\auth\AuthController{
 5
 6     protected function onConnect($connected) {
 7             $urlParts=$this->getOriginalURL();
 8             USession::set($this->_getUserSessionKey(), $connected);
 9             if(isset($urlParts)){
10                     Startup::forward(implode("/",$urlParts));
11             }else{
12                     Startup::forward("admin");
13             }
14     }
15
16     protected function _connect() {
17             if(URequest::isPost()){
18                     $email=URequest::post($this->_getLoginInputName());
19                     $password=URequest::post($this->_getPasswordInputName());
20                     return DAO::uGetOne(User::class, "email=? and password= ?",false,[$email,$password]);
21             }
22             return;
23     }
24
25     /**
26      * {@inheritDoc}
27      * @see \Ubiquity\controllers\auth\AuthController::isValidUser()
28      */
29     public function _isValidUser($action=null): bool {
30             return USession::exists($this->_getUserSessionKey());
31     }
32
33     public function _getBaseRoute(): string {
34             return 'BaseAuthController';
35     }
36     /**
37      * {@inheritDoc}
38      * @see \Ubiquity\controllers\auth\AuthController::_getLoginInputName()
39      */
40     public function _getLoginInputName(): string {
41             return "email";
42     }
43}

Modification du contrôleur Admin

Modifiez le contrôleur d’administration pour utiliser BaseAuthController :

app/controllers/Admin.php
1class Admin extends UbiquityMyAdminBaseController{
2     use WithAuthTrait;
3     protected function getAuthController(): AuthController {
4             return $this->_auth ??= new BaseAuthController($this);
5     }
6}

Tester l’interface d’administration à l’adresse /admin:

../_images/adminForbidden.png

Après avoir cliqué sur login :

../_images/formLogin.png

Si les données d’authentification sont invalides :

../_images/invalidCreditentials.png

Si les données d’authentification sont valides :

../_images/adminWithAuth.png

Attachement de la zone info-user

Modifier le contrôleur BaseAuthController :

app/controllers/BaseAuthController.php
1 /**
2 * Auth Controller BaseAuthController
3 **/
4class BaseAuthController extends \Ubiquity\controllers\auth\AuthController{
5...
6     public function _displayInfoAsString(): bool {
7             return true;
8     }
9}

La zone _userInfo est désormais présente sur toutes les pages de l’administration :

../_images/infoUserZone.png

Elle peut être affichée dans n’importe quelle vue twig :

{{ _userInfo | raw }}

Description des caractéristiques

Personnalisation des templates

template index.html

Le template index.html gère la connexion :

../_images/template_authIndex.png

Exemple avec la zone _userInfo :

Créez un nouveau AuthController nommé PersoAuthController :

../_images/createAuthForm2.png

Modifiez le template app/views/PersoAuthController/info.html.

app/views/PersoAuthController/info.html
 1{% extends "@framework/auth/info.html" %}
 2{% block _before %}
 3     <div class="ui tertiary inverted red segment">
 4{% endblock %}
 5{% block _userInfo %}
 6     {{ parent() }}
 7{% endblock %}
 8{% block _logoutButton %}
 9     {{ parent() }}
10{% endblock %}
11{% block _logoutCaption %}
12     {{ parent() }}
13{% endblock %}
14{% block _loginButton %}
15     {{ parent() }}
16{% endblock %}
17{% block _loginCaption %}
18     {{ parent() }}
19{% endblock %}
20{% block _after %}
21             </div>
22{% endblock %}

Changez le contrôleur AuthController Admin :

app/controllers/Admin.php
1class Admin extends UbiquityMyAdminBaseController{
2     use WithAuthTrait;
3     protected function getAuthController(): AuthController {
4             return $this->_auth ??= new PersoAuthController($this);
5     }
6}
../_images/adminWithAuth2.png

Personnalisation des messages

app/controllers/PersoAuthController.php
 1class PersoAuthController extends \controllers\BaseAuth{
 2...
 3 /**
 4  * {@inheritDoc}
 5  * @see \Ubiquity\controllers\auth\AuthController::badLoginMessage()
 6  */
 7 protected function badLoginMessage(\Ubiquity\utils\flash\FlashMessage $fMessage) {
 8     $fMessage->setTitle("Erreur d'authentification");
 9     $fMessage->setContent("Login ou mot de passe incorrects !");
10     $this->_setLoginCaption("Essayer à nouveau");
11
12 }
13...
14}

Auto-vérification

app/controllers/PersoAuthController.php
 1class PersoAuthController extends \controllers\BaseAuth{
 2...
 3 /**
 4  * {@inheritDoc}
 5  * @see \Ubiquity\controllers\auth\AuthController::_checkConnectionTimeout()
 6  */
 7 public function _checkConnectionTimeout() {
 8     return 10000;
 9 }
10...
11}

Limitation du nombre de tentatives

app/controllers/PersoAuthController.php
 1class PersoAuthController extends \controllers\BaseAuth{
 2...
 3 /**
 4  * {@inheritDoc}
 5  * @see \Ubiquity\controllers\auth\AuthController::attemptsNumber()
 6  */
 7 protected function attemptsNumber(): int {
 8     return 3;
 9 }
10...
11}

Récupération de compte

La récupération de compte se fait en réinitialisant le mot de passe du compte.
Un e-mail de réinitialisation du mot de passe est envoyé, à une adresse e-mail correspondant à un compte actif.

../_images/recoveryInit.png
app/controllers/PersoAuthController.php
 1class PersoAuthController extends \controllers\BaseAuth{
 2...
 3 protected function hasAccountRecovery():bool{
 4     return true;
 5 }
 6
 7 protected function _sendEmailAccountRecovery(string $email,string $validationURL,string $expire):bool {
 8     MailerManager::start();
 9     $mail=new AuthAccountRecoveryMail();
10     $mail->to($connected->getEmail());
11     $mail->setUrl($validationURL);
12     $mail->setExpire($expire);
13     return MailerManager::send($mail);
14 }
15
16 protected function passwordResetAction(string $email,string $newPasswordHash):bool {
17     //To implement for modifying the user password
18 }
19
20 protected function isValidEmailForRecovery(string $email):bool {
21     //To implement: return true if a valid account match with this email
22 }
23}
../_images/recoveryForm.png

Note

Par défaut, le lien ne peut être utilisé que sur la même machine, dans une période de temps prédéterminée (qui peut être modifiée en surchargeant la méthode accountRecoveryDuration).

Activation de MFA/2FA

L’authentification multi-facteurs peut être activée de manière conditionnelle, sur la base des informations de l’utilisateur préalablement connecté.

Note

La phase 2 de l’authentification est réalisée dans l’exemple ci-dessous en envoyant un code aléatoire par email. La classe AuthMailerClass est disponible dans le paquet Ubiquity-mailer.

app/controllers/PersoAuthController.php
 1class PersoAuthController extends \controllers\BaseAuth{
 2...
 3 /**
 4  * {@inheritDoc}
 5  * @see \Ubiquity\controllers\auth\AuthController::has2FA()
 6  */
 7 protected function has2FA($accountValue=null):bool{
 8     return true;
 9 }
10
11 protected function _send2FACode(string $code, $connected):void {
12     MailerManager::start();
13     $mail=new AuthMailerClass();
14     $mail->to($connected->getEmail());
15     $mail->setCode($code);
16     MailerManager::send($mail);
17 }
18...
19}
../_images/2fa-code.png

Note

Il est possible de personnaliser la création du code généré, ainsi que le préfixe utilisé. L’exemple ci-dessous est implémenté avec la bibliothèque robthree/twofactorauth.

protected function generate2FACode():string{
        $tfa=new TwoFactorAuth();
        return $tfa->createSecret();
}

protected function towFACodePrefix():string{
        return 'U-';
}

Création de compte

L’activation de la création du compte est également optionnelle :

../_images/account-creation-available.png
app/controllers/PersoAuthController.php
1class PersoAuthController extends \controllers\BaseAuth{
2...
3 protected function hasAccountCreation():bool{
4     return true;
5 }
6...
7}
../_images/account-creation.png

Dans ce cas, la méthode _create doit être surchargée afin de créer le compte :

protected function _create(string $login, string $password): ?bool {
        if(!DAO::exists(User::class,'login= ?',[$login])){
                $user=new User();
                $user->setLogin($login);
                $user->setPassword($password);
                URequest::setValuesToObject($user);//for the others params in the POST.
                return DAO::insert($user);
        }
        return false;
}

Vous pouvez vérifier la validité/disponibilité du login avant de valider le formulaire de création de compte :

protected function newAccountCreationRule(string $accountName): ?bool {
        return !DAO::exists(User::class,'login= ?',[$accountName]);
}
../_images/account-creation-error.png

Une action de confirmation (vérification par courriel) peut être demandée à l’utilisateur :

protected function hasEmailValidation(): bool {
        return true;
}

protected function _sendEmailValidation(string $email,string $validationURL,string $expire):void {
        MailerManager::start();
        $mail=new AuthEmailValidationMail();
        $mail->to($connected->getEmail());
        $mail->setUrl($validationURL);
        $mail->setExpire($expire);
        MailerManager::send($mail);
}

Note

Il est possible de personnaliser ces parties en surchargeant les méthodes associées, ou en modifiant les interfaces dans les modèles concernés.