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 loginCertains 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ôleLes droits d'un utilisateur sont conditionnés à différents critères, dont :
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
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 :
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.
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/
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
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 :
applyToCollectionapplyToItemaddWhereLes deux premières permettent de tester si l'extension doit s'appliquer à la ressource.
La dernière ajoute la condition en question.
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.
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
Le client est autorisé à consulter l'enregistrement si l'une de ces conditions est vraie :
Est autorisé à éditer si :
Est autorisé à créer si :
Est autorisé à supprimer si :