-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor permissions #35
base: main
Are you sure you want to change the base?
Changes from all commits
567cc58
cacae38
2d18cbc
e2686e3
cfe4d8b
113b417
ef9e624
11d5174
8ebdaca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,120 @@ | ||||||
# Permissions | ||||||
|
||||||
Cette page traite à la fois des permissions des utilisateurs, et de celles des applications utilisant l'API. | ||||||
|
||||||
Tous les termes spécifiques aux permissions seront en _italique_, et leur définition peut être retrouvée dans la partie [terminologie](#terminologie). | ||||||
|
||||||
## Terminologie | ||||||
|
||||||
### Permission | ||||||
|
||||||
Une _permission_ est une autorisation de réaliser une action ou d'accéder à des données. Dès que quelque chose ne devrait pas être accessible / faisable avec n'importe quelle _clé API_, une _permission_ pour faire cette dite chose doit exister. | ||||||
|
||||||
Les _permissions_ sont divisées en 2 catégories : les _user permissions_ et les _API permissions_. | ||||||
|
||||||
**Exemples :** La permission permettant de voir les commentaires des UEs, la permission permettant de modifier les permissions des autres, ... | ||||||
|
||||||
### User permission | ||||||
|
||||||
Une _user permission_ est un type de _permission_. Ces _permissions_ sont les _permissions_ liées à un utilisateur. | ||||||
|
||||||
**Exemples :** accéder aux données privées des utilisateurs, modifier les données d'un utilisateur, ... | ||||||
|
||||||
### API permission | ||||||
Une _API permission_ est un type de _permission_. Ces _permissions_ sont les _permissions_ générales, qui portent sur toute l'API. | ||||||
|
||||||
**Exemples :** modérer les commentaires, modérer les annales, etc... | ||||||
|
||||||
### Application | ||||||
|
||||||
Une application est un logiciel ayant besoin d'un accès à l'API de EtuUTT. Chaque application est reliée à un utilisateur, qui est l'administrateur de celle-ci. | ||||||
|
||||||
**Exemples :** le front de EtuUTT, l'application EtuUTT, le site de l'intégration, ... | ||||||
|
||||||
### Clé API (ou Api Key) | ||||||
|
||||||
Une _clé API_ (ou _Api Key_) est une relation entre un utilisateur et une _application_. Un utilisateur ne peut avoir qu'une _clé API_ par _application_. | ||||||
|
||||||
```{note} | ||||||
Une _clé API_ **n'est pas** un token, c'est plutôt un objet qui servira à générer un token et authentifier les requêtes. | ||||||
|
||||||
Un utilisateur n'a pas nécessairement les mêmes droits sur les différentes _applications_. Il est tout de même important de noter que rien ne l'empêchera d'utiliser une _clé API_ sur une _application_ qui n'est pas liée à cette _clé API_. Il est donc important **d'avoir confiance** en l'utilisateur, et pas uniquement en l'application. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Mais sinon, on peut imaginer un travail de déchiffrement de la clé renvoyée par l'api du site étu. Mais ça veut dire que les requêtes doivent passer par un backend intermédiaire There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Par rapport au requested change, nope, c'est pas ça, c'est pas l'user qui donne des perms a sa clé api, c'est les gens concernés (admins, autres utilisateurs, ou lui dans le cas spécifique du front-end) |
||||||
``` | ||||||
|
||||||
**Exemple :** prenons l'exemple de l'intégration : ils auront : | ||||||
* Une _clé API_ pour le pour se connecter au front de EtuUTT avec le compte `[email protected]` (reliée à l'_application_ `EtuUTT-front`) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
* Une _clé API_ pour le back de leur site web (reliée à `Integration-website`) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ça dépend non ? pourquoi il ne pourrait pas y avoir une key/user si on veut accéder à des données privées des utilisateurs par exemple ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ça serait le cas sur une application, sur un site web autant juste donner des permissions à la clé |
||||||
* Une _clé API_ par utilisateur de leur application (qui n'utiliserait pas le backend de leur site web), avec uniquement les droits de base, pour leur application (reliées à `Integration-app`). Chaque _clé API_ a des permissions différentes, ce qui signifie qu'on peut donner des droits à un utilisateur en particulier sur l'_application_ de l'intégration. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A reformuler, comme ça si j'ai bien compris
Suggested change
|
||||||
|
||||||
### Bearer token | ||||||
|
||||||
Le _bearer token_ est une chaîne de caractère encodant une certaine _clé API_, en utilisant le standard JWT. | ||||||
|
||||||
### Soft grant | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. J'ai définitivement pas compris l'idée d'avoir une clé unique pour une application avec des soft grants et hard grants au lieu d'avoir une clé pour chaque utilisateur. De cette façon. Les fois où l'appli n'a pas besoin de faire une opération en tant qu'un utilisateur particulier (ex. accéder au profil de Jean-Patrick en étant connecté en tant que le dit Jean-Patrick), et bien ça n'arrive pas puisque ces données là sont publiques ? Et si jamais une appli devait accéder à une section privée du site étu (les commentaires des UEs par exemple) et à y donner accès sans login dans ce cas le developpeur n'a cas générer une key et faire accéder son site/app on his behalf, même s'il ne devrait théoriquement pas avoir le droit de le faire (puisque si une appli fait fuiter les commentaires des UEs qui ne sont pas censés être visibles des enseignants, c'est gênant) Si c'est au niveau du stockage du token, ce token peut rester sur le front en soit et même ça pourrait être le front lui même qui effectuerait ces requêtes ? (je suis pas sûr de l'idée) ou sinon stocké dans la session côté serveur (et transmis lors de la connexion via le site étu) ou sinon mis dans une db (ce qui ne serait pas une guideline) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Les données des utilisateurs sont pas publiques 😅 |
||||||
|
||||||
Un _soft grant_ ne peut se faire que sur des _user permissions_ (ça n'aurait pas de sens sur des _api permissions_). | ||||||
|
||||||
Les _soft grant_ ne donne pas la permission à la _clé API_ sur tous les utilisateurs. Chaque utilisateur doit explicitement donner son consentement pour que la _clé API_ puisse exercer sa _permission_ sur son compte. | ||||||
|
||||||
Une _clé API_ peut se soft grant n'importe quelle _user permission_. Tant qu'elle n'aura reçu le consentement de personne, elle n'aura aucun droit supplémentaire. | ||||||
|
||||||
**Exemple :** Guillaume, grand rageux qu'il est, décide de développer une application, qui permet d'avoir une interface bien plus agréable que celle de EtuUTT. Il a aussi une API (en Rust, on se respecte), qui s'occupe de faire l'interface entre l'API EtuUTT et son application. Guillaume pourra donner la _permission_ à sa clé API de voir le détail des utilisateurs. Cependant, ce sera un _soft grant_, ce qui signifie qu'il n'aura au début accès aux détails d'aucun utilisateur. Teddy va alors être curieux du projet, et se connecter à son application. Pendant l'authentification avec EtuUTT, il devra donner son consentement pour que Guillaume puisse récupérer ses informations personnelles. À partir de ce moment là, Guillaume pourra utiliser sa permission sur Teddy, mais **uniquement** sur Teddy, jusqu'à ce qu'un autre utilisateur lui donne son consentement. (Ah, au fait, Teddy a pas aimé l'application et a revoke son consentement 😔) | ||||||
|
||||||
### Hard grant | ||||||
|
||||||
Un _hard grant_ peut se faire sur n'importe quel type de _permissions_ (_user permissions_ et _API permissions_). | ||||||
|
||||||
Un _hard grant_ ne nécessite le consentement de personne, et s'applique sur tous les utilisateurs. Une _clé API_ ne peut évidemment pas se _hard grant_ des _permissions_. | ||||||
|
||||||
Une _API permissions_ est nécessairement _hard granted_ (aucun sens de les _soft grant_). | ||||||
|
||||||
**Exemple :** Guillaume rêve de pouvoir. Et finalement, il a amélioré son application (Teddy est revenu sur son choix). Son code est devenu propriété de l'UNG (merci Guillaume). Nous pouvons donc donner la _permission_ pour voir les informations personnelles des utilisateurs à l'application. Un administrateur va alors _hard grant_ la permission à Guillaume. Les utilisateurs n'ont pas besoin de donner leur consentement, Guillaume aspire tout 😈. | ||||||
|
||||||
```{warning} | ||||||
Attenation cependant à bien respecter le RGPD en faisant un _hard grant_ d'une _user permission_ ! \ | ||||||
À ce jour, nous ne pensons qu'à 2 _applications_ qui devraient en avoir besoin : le site de EtuUTT, et son application. | ||||||
``` | ||||||
|
||||||
## Tables | ||||||
|
||||||
Faisons un tour d'horizon des tables : | ||||||
- `Application` : représente une _application_. | ||||||
- `ApiKey` : représente une _clé API_. L'`ApiKey` contient un token, qui sera signé pour créer le Bearer token. | ||||||
- `User` : représente un utilisateur (rien de particulier à signaler ici, la table ressemble à ce dont vous pouvez vous attendre d'une table utilisateur) | ||||||
- `ApiKeyPermission` : Une _permission_ spécifique donnée à une certaine _clé API_. Cette _permission_ peut soit être _soft granted_ soit être _hard granted_. | ||||||
- `GrantedPermissions` : Cette table contient les permissions données par un certain utilisateur à une certaine clé API. | ||||||
- `Permission` : une _enum_ listant l'entièreté des _permissions_ prises en charge par l'API. Les _API permissions_ commencent par `API_`, et les _user permissions_ commencent par `USER_`. | ||||||
|
||||||
## Authentification des requêtes | ||||||
|
||||||
On va traiter l'authentification des requêtes avant la connexion, le _flow_ me paraît plus logique dans ce sens là 🙂 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pas la peine de raconter ta vie |
||||||
|
||||||
Pour authentifier les requêtes, on utilise un _bearer token_ (token JWT), passé dans le _header_ `Authorization`, sous le format `Bearer {token}`. Une fois décodé, le token renvoit un objet contenant un champ `token`. Ce champ permet de trouver une `ApiKey` unique. À partir de cette `ApiKey`, il est ainsi possible d'obtenir l'utilisateur authentifié, et les routes ou informations auxquelles l'utilisateur a le droit d'accéder. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allez c'est cadeau
Suggested change
|
||||||
|
||||||
## Connexion | ||||||
|
||||||
On fera la différence entre un utilisateur et une _application_. Mais comme vous avez dû le comprendre, un utilisateur n'est rien d'autre que l'_application_ du site web de EtuUTT essayant de se connecter en tant que cet utilisateur. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Vous avez du le comprendre est mal placé puisque tu n'as pas encoré précisé les différentes façons de se connecter There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ouais mais avec le fonctionnement que j'ai expliqué plus tot, c'est pas une conclusion logique ? |
||||||
|
||||||
La méthode de connexion "utilisateur" permettra donc de générer un _bearer token_ temporaire, avec une connexion standard (décentralisée, nom d'utilisateur / mot de passe). | ||||||
|
||||||
La méthode de connexion "application" permettra de générer un _bearer token_ avec une durée de vie possiblement infinie (en fonction de ce que veut l'utilisateur). On passe ici par une autre application (le site EtuUTT) pour générer un _bearer token_. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. J'ai un problème avec cette durée de vie de token potentiellement infinie... C'est contraire a plein de règles de sécurité. Alors oui ça permet d'éviter d'avoir à se reconnecter mais il serait plus sécuritaire de renouveler régulièrement le jwt - automatiquement de façon complètement transparente, par exemple en renvoyant un header spécifique avec la réponse ou de trouver une façon de le rotate - plutôt que de pouvoir lui donner une durée de vie infinie... Si un token arrive à expiration, l'application refait la demande de connexion à l'application dont la clé émane. Si l'utilisateur est connecté, le token est regen instant sinon il doit rentrer ses identifiants, seems legit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C'était pas vraiment pour ce cas là, c'était plus pour les applis ou on a la flm de modifier les env vars tous les 4 matins |
||||||
|
||||||
### Pour un utilisateur | ||||||
|
||||||
Pour un utilisateur, on passe par le CAS de l'UTT, avec la route `POST /auth/signin`, puis l'API nous renvoit un token pour authentifier nos requêtes, voir la partie (Authentification des requêtes)[#authentification-des-requetes] | ||||||
|
||||||
### Pour une application | ||||||
|
||||||
Pour une application, on génère un token pour la _clé API_ demandée, puis on retourne le _bearer token_ associé. Il faut aussi bien sauvegarder la date de dernière mise à jour (`tokenUpdatedAt`), et utiliser cette date pour toujours retourner la même version du token (champ `iat` dans l'objet à encoder avec JWT). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rajouter le nom de la table avec Maintenant (je pense que j'aurai la réponse quand je lirai le code) mais j'imagine que c'est pour mitiger le fait que la durée de vie puisse être infinie:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sinon sur tout ce qui est route login, on empêche le token d'être infini ? Et sur les routes de gestion des api keys, on leur permet ? |
||||||
|
||||||
L'utilisateur peut renouveler les token de ses `ApiKey`. Le token sera alors modifié, pour empêcher l'accès avec l'ancien token. | ||||||
|
||||||
## Grant | ||||||
|
||||||
### Soft grant | ||||||
|
||||||
N'importe quelle application peut se _soft grant_ une _permission_. | ||||||
|
||||||
Pour permettre à un utilisateur d'accepter cette _soft grant_, l'_application_ doit rediriger l'utilisateur vers une route sur le front{sup}`route à déterminer`, en lui passant en paramètre l'id de l'_application_, l'URL de redirection, et les IDs des `ApiKeyPermission` pour nécessaires à _l'application_{sup}`noms des arguments à déterminer`. | ||||||
|
||||||
L'utilisateur sera alors invité à se connecter, à accepter ou refuser les différentes _permissions_, et sera redirigé vers l'URL, avec en paramètre les _permissions_ acceptées{sup}`format à déterminer`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Peut être rappeler que les applis agissent "on the behalf of the user" et que l'utilisateur doit avoir les permissions afin que la clé puisse accéder à la dite permission. (eg. modérer les commentaires, etc)