Helper contrôleur Auth


1Présentation

Ce helper sert à gérer l'authentification des utilisateurs d'un site web. C'est à la fois le contrôleur qui offre l'interface pour s'authentifier, mais aussi le plugin qui transmet l'information d'authentification aux autres plugins/contrôleurs.

Le système d'authentification proposé est sans mot de passe : l'utilisateur saisit son adresse mail, et si elle est connue en base de données, un message est envoyé à cette adresse, contenant un lien. En cliquant sur le lien, l'utilisateur revient sur le site en étant authentifié. Le lien n'est utilisable qu'une seule fois et a une durée de vie limitée à une heure.

Par défaut, le contrôleur n'accepte que la connexion d'utilisateurs qui ont déjà été ajoutés par ailleurs en base de données. Mais il est possible de le configurer pour que les nouveaux utilisateurs soient inscrits lorsqu'ils saisissent leur adresse mail pour la première fois.


2Base de données

Ce helper nécessite deux tables en base de données, l'une nommée User (contenant les informations sur les utilisateurs), l'autre nommée AuthToken (contenant les jetons de connexion envoyés par email).

La table User doit contenir les champs suivants :

  • id (int) : Clé primaire.
  • date_creation (datetime) : Date de création de l'utilisateur.
  • date_last_login (datetime) : Date de dernière authentification de l'utilisateur.
  • date_last_access (datetime) : Date de dernier accès de l'utilisateur.
  • email (string) : Adresse mail de l'utilisateur.
  • name (string) : Nom de l'utilisateur (champ obligatoire, même si vous ne l'utilisez pas).
  • roles (set) : Rôles assignés à l'utilisateur.
  • services (set) : Services auxquels l'utilisateur a accès.

La table AuthToken doit contenir les champs suivants :

  • token (string) : Empreinte numérique (algorithme SHA-256) du jeton de connexion.
  • expiration (datetime) : La date et heure d'expiration du jeton.
  • user_id (int) : Clé étrangère vers l'utilisateur.

Voici un exemple de requête de création de ces tables, dont vous devez personnaliser les champs roles et services de la table User :

CREATE TABLE User (
    id               INT UNSIGNED NOT NULL AUTO_INCREMENT,
    date_creation    DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_last_login  DATETIME,
    date_last_access DATETIME,
    email            TINYTEXT CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
    name             TINYTEXT,
    roles            SET('admin', 'writer', 'reviewer'), -- à personnaliser
    services         SET('articles', 'news', 'images'), -- à personnaliser
    PRIMARY KEY (id),
    UNIQUE INDEX email (email(255))
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

CREATE TABLE AuthToken (
    token         CHAR(64) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
    expiration    DATETIME NOT NULL,
    user_id       INT UNSIGNED NOT NULL,
    PRIMARY KEY (token),
    INDEX expiration (expiration),
    FOREIGN KEY (user_id) REFERENCES User (id) ON DELETE CASCADE
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

3Configuration du plugin et du contrôleur

Vous devez ajouter l'objet \Temma\Controllers\Auth comme pré-plugin dans la configuration Temma, et créer une route pour rendre le contrôleur accessible :

<?php

return [
    'plugins' => [
        '_pre' => [
            '\Temma\Controllers\Auth'
        ]
    ],
    'routes' => [
        'auth' => '\Temma\Controllers\Auth'
    ]
];

4Configuration des messages de connexion

Voici les paramètres par défaut utilisés pour envoyer les messages de connexion :

  • Adresse mail de l'expéditeur : contact@ + nom de domaine de votre site
  • Titre du message : Your connection link
  • Texte du message :
    Hi,
    
    Here is your connection link:
    %s
    
    It is valid for 1 hour and can only be used once.
    
    Best regards

Il est possible de modifier ces paramètres :

<?php

return [
    'x-security' => [
        'auth' => [
            'emailSender'  => 'no-reply@mycompany.com',
            'emailSubject' => 'Votre lien de connexion',
            'emailText'    => 'Voici votre lien de connexion : %s'
        ]
    ]
];
  • Ligne 6 : Adresse mail de l'expéditeur du message.
  • Ligne 7 : Titre du message de connexion.
  • Ligne 8 : Contenu du message, en texte brut. Le marqueur %s est remplacé par l'URL de connexion.

Le contrôleur utilise l'objet \Temma\Utils\Email pour envoyer les messages de connexion. Il est donc possible d'utiliser la configuration de cet objet pour désactiver les envois, pour n'autoriser que les envois vers certains domaines, ou encore ajouter des destinataires en copie ou en copie cachée.


5Configuration de l'inscription des utilisateurs

Pour que les utilisateurs qui ne sont pas en base de données soient inscrits automatiquement, il suffit d'ajouter cette configuration :

<?php

return [
    'x-security' => [
        'auth' => [
            'registration' => true
        ]
    ]
];

6Configuration des redirections

Par défaut, une fois qu'un utilisateur est authentifié, il est redirigé vers la page d'accueil du site. Il est possible de configurer une URL différente :

<?php

return [
    'x-security' => [
        'auth' => [
            'redirection' => '/monCompte'
        ]
    ]
];

Notez que s'il existe une variable de session nommée authRequestedUrl, son contenu sera utilisé pour effectuer la redirection (et la variable est effacée de la session). Cette variable peut être définie par l'attribut Auth, si son paramètre storeUrl est mis à true.


7Configuration de la base de données

Par défaut, les noms des tables et des champs sont ceux indiqués plus haut, et ces tables doivent être placées dans la base ouverte par la connexion nommée db dans la directive de configuration dataSources. Vous avez la possibilité d'indiquer le nom de la base, les nom des tables, ainsi que les noms des champs, s'ils sont différents des noms par défaut :

<?php

return [
    'x-security' => [
        'auth' => [
            'userData' => [
                'base'     => 'auth_app',
                'table'    => 'tUser',
                'id'       => 'user_id',
                'email'    => 'user_mail',
                'roles'    => 'user_roles',
                'services' => 'user_services',
            },
            'tokenData' => [
                'base'       => 'auth_app',
                'table'      => 'tToken',
                'token'      => 'token_string',
                'expiration' => 'expiration_date',
                'user_id'    => 'identifier_user',
            ]
        ]
    ]
];
  • Lignes 6 à 13 : Configuration de la table des utilisateurs.
    • Ligne 7 : Nom de la base de données qui contient la table.
    • Ligne 8 : Nom de la table.
    • Ligne 9 : Nom du champ contenant la clé primaire.
    • Ligne 10 : Nom du champ contenant l'adresse mail de l'utilisateur.
    • Ligne 11 : Nom du champ contenant les rôles de l'utilisateur.
    • Ligne 12 : Nom du champ contenant les services auxquels l'utilisateur a accès.
  • Lignes 14 à 20 : Configuration de la table des jetons de connexion.
    • Ligne 15 : Nom de la base de données qui contient la table.
    • Ligne 16 : Nom de la table.
    • Ligne 17 : Nom du champ contenant le jeton.
    • Ligne 18 : Nom du champ contenant la date d'expiration du jeton.
    • Ligne 19 : Nom du champ contenant l'identifiant de l'utilisateur.

Dans cet exemple, user_id, user_mail, user_roles et user_services sont les noms réels des champs de la table tUser, qui contient les utilisateurs.
Et token_string, expiration_date et identifier_user sont les noms réels des champs dans la table tToken, qui contient les jetons de d'authentification.

Si la table des utilisateurs contient d'autres champs que vous souhaitez récupérer, vous pouvez les ajouter à la liste. Si les champs ne doivent pas être renommés, mettez le même nom en clé et en valeur :

<?php

return [
    'x-security' => [
        'auth' => [
            'userData' => [
                'email'        => 'user_mail',
                'name'         => 'user_name',
                'organization' => 'organization',
                'birthday'     => 'birthday',
            ]
        ]
    ]
];
  • Ligne 7 : Définition du nom du champ qui contient l'adresse mail de l'utilisateur.
  • Ligne 8 : Ajout d'un champ user_name, renommé en name.
  • Ligne 9 : Ajout d'un champ organization, qui n'est pas renommé.
  • Ligne 10 : Ajout d'un champ birthday, qui n'est pas renommé.

8Configuration de la base de données par DAO

Plutôt que d'utiliser le fichier de configuration (etc/temma.php) pour définir les paramètres concernant la base de données, il est possible d'utiliser des DAO personnalisées.

Exemple de configuration :

<?php

return [
    'x-security' => [
        'auth' => [
            'userDao'  => '\MyApp\UserDao',
            'tokenDao' => '\MyApp\TokenDao',
        ]
    ]
];

Exemple de DAO :

namespace MyApp;

class UserDao extends \Temma\Dao\Dao {
    protected $_tableName = 'tUser';
    protected $_idField = 'use_i_id';
    protected $_fields = [
        'user_id'       => 'id',
        'user_mail'     => 'email',
        'user_roles'    => 'roles',
        'user_services' => 'services',
        'user_name'     => 'name',
        'organization',
        'birthday',
    ];
}

9URLs du contrôleur

Le contrôleur offre les URLs suivantes :

  • /auth/login : Page contenant le formulaire d'authentification.
  • /auth/logout : URL vers laquelle envoyer l'utilisateur pour qu'il soit déconnecté.

L'URL /auth effectue une redirection vers /auth/login.


10Template

Le contrôleur utilise un template Smarty placé dans templates/auth/login.tpl. La version fournie par Temma est minimale, il vous est recommandé de vous en inspirer pour créer votre propre version.


11Variables de template

Le plugin positionne les variables de template suivantes :

  • currentUserId : Identifiant de l'utilisateur actuellement authentifié.
  • currentUser : Données de l'utilisateur courant. Il s'agit d'un tableau associatif contenant les clés suivantes :
    • id : Identifiant de l'utilisateur.
    • date_creation : Date de création de l'utilisateur.
    • date_last_login : Date de la dernière authentification de l'utilisateur.
    • date_last_access : Date du dernier accès de l'utilisateur.
    • email : Adresse mail de l'utilisateur.
    • name : Nom de l'utilisateur.
    • roles : Tableau associatif dont les clés sont les rôles de l'utilisateur (associées à la valeur true).
    • services : Tableau associatif dont les clés sont les services auxquels l'utilisateur a accès (associées à la valeur true).

Ces variables sont utilisables dans les autres plugins, les contrôleurs et les templates.


12Attribut Auth

Temma fournit l'attribut Auth, qui permet de spécifier si un contrôleur ou une action ne peut être accédé que par un utilisateur authentifié (ou non). Cet attribut se basant que la présence d'une variable de template currentUser (ainsi que sur ses clés roles et services), il est pleinement compatible avec ce helper.

Par exemple, il est possible d'indiquer qu'un contrôleur n'est accessible qu'aux utilisateurs connectés :

use \Temma\Attributes\Auth as TµAuth;

#[TµAuth]
class Account extends \Temma\Web\Controller {
    // ...
}

Il est aussi possible de faire en sorte que des contrôleurs ou des actions ne soient accessibles qu'aux utilisateurs ayant un rôle spécifique ou ayant accès à un service particulier :

use \Temma\Attributes\Auth as TµAuth;

class MonControleur extends \Temma\Web\Controller {
    // accès autorisé uniquement aux utilisateurs
    // ayant le rôle "manager"
    #[TµAuth('manager')]
    public function action1() { }

    // autorisé uniquement aux utilisateurs
    // ayant accès au service "images" ou au
    // service "text"
    #[TµAuth(service: ['images', 'text'])]
    public function action2() { }
}

Référez-vous à la documentation de l'attribut pour voir toutes ses capacités.