security.md 6.8 KB

Security

Authentification Symfony

Fonctionnement de base

L'authentification se fait via une requête POST envoyée à l'adresse /login_check avec le body suivant :

{
    "username": "login",
    "password": "password"
}

En cas de succès, la requête renvoie un token qui servira ensuite à l'utilisateur à s'identifier.

Les requêtes suivantes devront posséder les headers suivants :

  • x-accessid : l'id de l'utilisateur (ou Access)
  • authorization : une chaine de caractères de la forme "BEARER XXXXX", où XXXXX est le token retourné par la requête de login

Connexion Switch

Certains utilisateurs (admins, familles) peuvent prendre le rôle d'un autre utilisateur via la connexion switch.

Pour ce faire, un nouveau header doit être ajouté aux requêtes :

  • x-switch-user: l'id de l'utilisateur dont on veut prendre le rôle

Roles et Modules

Les droits d'un utilisateur sont conditionnés à différents critères, dont :

  • Les modules que possède l'organisation à laquelle il est appartient
  • Les rôles de cet utilisateur au sein de cette organisation

On peut obtenir la liste des modules de l'organisation et des rôles de l'utilisateur actif en son sein au moyen de la requête : /api/my_profile

Modules

Les modules d'une organisation dépendent du produit acheté par celle-ci et des éventuels modules complémentaires. Ces deux informations sont stoquées dans la table Settings.

Le fichier config/opentalent/products.yaml définit :

  • L'appartenance des modules aux products
  • L'appartenance des entities aux modules

De plus, le fichier config/opentalent/modulesbyconditions.yaml complète cette configuration en définissant des modules présentant des conditions particulières (appartenance à la CMF en particulier)

A chaque requête effectuée, la classe \App\Security\Voter\ModuleVoter vérifie si la ressource demandée appartient à un module possédé par l'organisation de l'utilisateur. Si ce n'est pas le cas, une erreur AccessDeniedHttpException est levée.

Différentes méthodes de sécurisation

Les annotations Api-Platform

La sécurité des ApiResources peut être définie de manière globale pour la ressource, ou pour chaque opération (Get, GetCollection, Put, Post, Delete) via les annotations.

Exemple :

#[ApiResource(
    operations: [
        new Get(
            security: '(is_granted("ROLE_ORGANIZATION_VIEW") or is_granted("ROLE_ORGANIZATION")) and object.getOrganization().getId() == user.getOrganization().getId()'
        ),
        new Put(
            security: 'is_granted("ROLE_ORGANIZATION") and object.getOrganization().getId() == user.getOrganization().getId()'
        )
    ],
)]

Dans certains cas plus complexes (ex: Access), cette configuration peut être déplacée dans un fichier de configuration situé dans le répertoire ~/config/api_platform/ et portant le nom de la ressource.

Voir plus : https://api-platform.com/docs/core/security/

Voters

Les voters permettent de contrôler l'accès à certaines ressources, selon le type d'opération.

Ils implémentent essentiellement deux méthodes : supports et voteOnAttribute qui prennent en paramètres la ressource et le type d'opération. supports retourne true si le voter doit s'appliquer dans ce cas. Si oui, voteOnAttribute est appellée et retourne true si l'opération est autorisée.

TODO: quand faut-il retourner false et quand faut-il lever une AccessDeniedHttpException ?

Pour qu'un Voter soit appellé, il faut configurer la sécurité de la ressource via son annotation et utiliser la méthode is_granted combinée à une des constantes :

Exemple :

#[ApiResource(
    operations: [
        new Get(security: "is_granted('READ', object)"),
        new Put(security: "is_granted('EDIT', object)"),
        new Post(security: "is_granted('CREATE', object)"),
        new Delete(security: "is_granted('DELETE', object)"),
    ]
)]
class File

Les voters custom sont enregistrés dans le répertoire src/Security/Voter.

Voir plus : https://symfony.com/doc/current/security/voters.html

Extensions Doctrine

Le framework Api-Platform propose un système d'extensions doctrine pour ajouter des filtres automatiques aux opérations réalisées sur des ressources voulues.

Concrètement, l'extension ajoutera une condition au WHERE de la requête SQL.

Une extension implémente trois méthodes :

  • applyToCollection
  • applyToItem
  • addWhere

Les deux premières permettent de tester si l'extension doit s'appliquer à la ressource.

La dernière ajoute la condition en question.

Voir : https://api-platform.com/docs/core/extensions/

Quand utiliser les annotations, un Voter ou une Extension Doctrine ?

Si la sécurité doit pouvoir s'appliquer à une collection et filtrer le résultat de celle-ci (exemple: les notifications d'un utilisateur) : on utilisera une Extension Doctrine

Sinon, si les conditions d'accès peuvent s'écrire facilement avec l'expression language des annotations api-platform, on utilisera les annotations Api-platform.

Si aucune des conditions précédentes n'est remplie, on utilisera un Voter Symfony.

Internal Requests

Certaines routes de la forme /internal/... permettent d'accepter des requêtes sans que le client ne soit authentifié (cf config/packages/security.yaml), en se basant sur un contrôle de l'IP et un token.

Voir: https://gitlab.2iopenservice.com/opentalent/ap2i/-/blob/develop/doc/internal_requests.md

Cas particuliers

Les Fichiers

Le client est autorisé à consulter l'enregistrement si l'une de ces conditions est vraie :

  • pas de date de disponibilité ou date de disponibilité antérieure à Now
  • date de disponibilité postérieure à Now, mais utilisateur a le rôle ROLE_BILLACCOUNTING et le fichier est de type BILL (facture)
  • visibilité est 'EVERYBODY'
  • requête interne
  • est connecté et fait partie des AccessPersons du fichier
  • est connecté et est le propriétaire du fichier
  • est connecté et a le rôle ROLE_FILE et fichier appartient à l'utilisateur ou à son organisation
  • est connecté et fichier a des accessRoles et user a un des roles présents dans accessRoles et fichier appartient à l'utilisateur ou à son organisation (deprecated)

Est autorisé à éditer si :

  • pas de date de disponibilité ou date de disponibilité antérieure à Now
  • date de disponibilité postérieure à Now, mais utilisateur a le rôle ROLE_BILLACCOUNTING et le fichier est de type BILL (facture)
  • est connecté et a le rôle ROLE_FILE et fichier appartient à l'utilisateur ou à son organisation
  • est connecté et est le propriétaire du fichier

Est autorisé à créer si :

  • est connecté

Est autorisé à supprimer si :

  • est connecté et est autorisé à éditer