Je sais que ce n'est pas la première fois que le sujet est traité dans StackOverflow, cependant, j'ai des questions auxquelles je n'ai pas pu trouver de réponse ou d'autres questions se sont opposées.
Je suis en train de faire une API REST assez simple (Silex-PHP) qui doit être consommée initialement par un seul SPA (application de réseau principal). Je ne veux pas commenter toutes les méthodes d'authentification de cette question, car ce sujet est déjà entièrement couvert par SO. Je vais créer un jeton pour chaque utilisateur. Ce jeton sera attaché à chaque demande nécessitant une authentification par le SPA. Toutes les transactions du serveur SPA seront exécutées sous HTTPS. Pour l'instant, ma décision est que le jeton n'expire pas. Les jetons qui expirent/les jetons par session ne sont pas conformes à l'apatridie de REST, non? Je comprends qu'il y a beaucoup à faire pour améliorer la sécurité, mais c'est ce que je peux faire pour le moment.
J'ai un modèle pour les jetons, et donc une table dans la base de données pour les jetons avec un FK à user_id. J'entends par là que le jeton ne fait pas partie de mon modèle d'utilisateur.
J'ai un POST/users (ne nécessite aucune authentification) qui crée un utilisateur dans la base de données et renvoie le nouvel utilisateur. Ceci est conforme à la règle de ressource one request one. Cependant, cela m’amène certains doutes:
Mon idée est qu’au moment de créer un nouvel utilisateur, créez un nouveau jeton pour l’utilisateur, pour le renvoyer immédiatement avec la réponse, et ainsi améliorer l’UX. L'utilisateur pourra immédiatement commencer à utiliser l'application Web. Cependant, renvoyer le jeton pour une telle réponse enfreindrait la règle du renvoi de la ressource uniquement. Devrais-je plutôt faire deux demandes ensemble? Une pour créer l'utilisateur et une pour récupérer le jeton sans que l'utilisateur ait besoin de ressaisir ses informations d'identification?
Si je décidais de renvoyer le jeton avec l'utilisateur, je pense alors que POST/users créerait de la confusion pour le consommateur d'API, puis quelque chose comme POST/auth/register apparaît. Une fois de plus, je n'aime pas cette idée car implique un verbe. J'aime beaucoup la simplicité offerte dans cette réponse . Mais là encore, je devrais faire deux demandes ensemble, un POST/users et un POST/jetons. Comment est-il erroné de faire deux demandes ensemble et comment puis-je envoyer exactement les informations pertinentes pour que le jeton soit attaché à un utilisateur donné si les deux demandes sont envoyées ensemble?
Pour l'instant, mon flux fonctionne comme suit:
1. Register form makes a POST /users request
2. Server creates a new user and a new token, returns both in the response (break REST rule)
3. Client now attaches token to every Request that needs Authorization
Le jeton n'expire jamais, préservant REST l'apatridie.
La plupart des applications Web actuelles nécessitent une validation du courrier électronique sans casser l’UX pour les utilisateurs, c’est-à-dire que les utilisateurs peuvent utiliser immédiatement l’application Web après l’enregistrement. D'un autre côté, si je retourne le jeton avec la demande d'enregistrement comme suggéré ci-dessus, les utilisateurs auront immédiatement accès à toutes les ressources sans valider leurs courriels.
Normalement, je choisirais le flux de travail suivant:
1. Register form sends POST /users request.
2. Server creates a new user with validated_email set to false and stores an email_validation_token. Additionally, the server sends an email generating an URL that contains the email_validation_token.
3. The user clicks on the URL that makes a request: For example POST /users/email_validation/{email_validation_token}
4. Server validates email, sets validated_email to true, generates a token and returns it in the response, redirecting the user to his home page at the same time.
Cela semble trop compliqué et ruine totalement l'UX. Comment vous y prenez-vous?
C'est assez simple, pour le moment je le fais de cette façon alors corrigez-moi si je me trompe:
1. User fills a log in form which makes a request to POST /login sending Basic Auth credentials.
2. Server checks Basic Auth credentials and returns token for the given user.
3. Web app attached the given token to every future request.
login est un verbe et enfreint ainsi une règle REST. Tout le monde semble être d’accord pour le faire de cette façon.
Pourquoi tout le monde semble-t-il avoir besoin d'un point de terminaison/auth/logout? De mon point de vue, cliquer sur "Déconnexion" dans l'application Web devrait essentiellement supprimer le jeton de l'application et ne pas l'envoyer dans d'autres demandes. Le serveur ne joue aucun rôle dans cela.
Comme il est possible que le jeton soit conservé dans localStorage afin d'éviter de perdre le jeton lors d'une actualisation éventuelle de la page, la déconnexion impliquerait également la suppression du jeton de localStorage. Mais cela n’affecte pas le serveur. Je comprends que les personnes qui ont besoin d'un POST/logout travaillent en principe avec des jetons de session, ce qui brise encore l'apatridie de REST.
Je comprends que l’option Remember me fait référence à la sauvegarde du jeton renvoyé dans le stockage local ou pas dans mon cas. Est-ce correct?
Si vous recommandiez des lectures supplémentaires sur ce sujet, je l'apprécierais beaucoup. Merci!
Au départ, j'ai adopté l'approche /LOGON
et /LOGOUT
. Je commence à explorer /PRESENCE
. Il semble que cela m'aiderait à combiner la connaissance du statut de quelqu'un et son authentification.
0 = Offline
1 = Available
2 = Busy
Le passage de Offline
à toute autre option devrait inclure la validation initiale (nécessite également un nom d’utilisateur/mot de passe). Vous pouvez utiliser PATCH
ou PUT
pour cela (selon votre vision).