Supposons que j'ai une API REST qui est également utilisée pour définir/réinitialiser les mots de passe. Supposons également que cela fonctionne sur une connexion HTTPS. Y a-t-il une bonne raison de ne pas mettre ce mot de passe dans le chemin d'appel , disons aussi que je vais l'encoder en BASE64?
Un exemple serait de réinitialiser un mot de passe comme celui-ci:
http://www.example.com/user/joe/resetpassword/OLDPASSWD/NEWPASSWD
Je comprends que BASE64 n'est pas un cryptage, mais je veux seulement protéger le mot de passe pour surfer sur l'épaule dans ce cas.
Un bon serveur enregistre toutes les requêtes qui lui sont envoyées, y compris les URL (souvent, sans partie variable après '?'), L'adresse IP source, le temps d'exécution ... Voulez-vous vraiment que ce journal (potentiellement lu par un large groupe d'administrateurs) contienne des informations sécurisées en tant que mots de passe? Base64 n'est pas un frein contre eux.
Ce que vous proposez n'est ni sécurisé ni RESTful.
@Netch a déjà mentionné le problème des journaux, mais il y a aussi un autre problème dans le fait que vous montrez les mots de passe envoyés par HTTP, ce qui rend trivial la capture de mots de passe avec n'importe quel type de renifleur de fil ou d'attaque de l'homme du milieu.
Lorsque vous effectuez une demande GET à l'aide de REST, les différents éléments de l'URL représentent des éléments plus fins. Votre URL se lit comme si vous renvoyiez une partie NEWPASSWD d'un OLDPASSWD faisant partie d'un mot de passe de réinitialisation. Cela n'a aucun sens sémantique. Les GET ne doivent pas être utilisés pour enregistrer des données.
Vous devriez faire quelque chose comme ça:
POST https://www.example.com/user/joe/resetpassword/
{oldpasswd:[data], newpasswd:[data]}
POST parce que vous écrivez des données et https parce que vous ne voulez pas qu'elles soient reniflées.
(C'est vraiment la sécurité de la barre basse. Le minimum absolu que vous devriez faire.)
Le schéma proposé présente des problèmes dans plusieurs domaines.
Sécurité
Les chemins d'URL sont fréquemment enregistrés; mettre des mots de passe non hachés dans le chemin est une mauvaise pratique.
[~ # ~] http [~ # ~]
Les informations d'authentification/autorisation doivent apparaître dans l'en-tête d'autorisation. Ou potentiellement, pour les éléments basés sur un navigateur, l'en-tête Cookie.
[~ # ~] reste [~ # ~]
Les verbes tels que resetpassword
dans votre URL sont généralement un signe clair d'un paradigme de transfert d'état non représentatif. Une URL doit représenter une ressource. Que signifie GET resetpassword
? Ou SUPPRIMER?
[~ # ~] api [~ # ~]
Ce schéma nécessite de toujours connaître le mot de passe précédent. Vous voudrez probablement autoriser plus de cas; par exemple. le mot de passe est perdu.
Vous pouvez utiliser authentification de base ou Digest , qui sont des schémas bien compris.
PUT /user/joe/password HTTP/1.0
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: text/plain
Host: www.example.com
NEWPASSWD
Il ne met pas d'informations ultra-sensibles dans le chemin et suit les conventions HTTP et REST.
Si vous devez autoriser un autre mode d'autorisation (par exemple, un jeton envoyé via un canal vérifié pour réinitialiser le mot de passe), vous pouvez simplement utiliser un en-tête d'autorisation différent sans avoir à changer quoi que ce soit d'autre.
Le problème est d'éviter les mots de passe en texte brut dans vos demandes. Il existe deux options pour répondre aux exigences de service Web reposantes.
1. Hachage côté client
2. Cryptage
Remarque: HTTPS est requis pour les deux options!
En dehors de la sécurité, le problème est que ce n'est pas une approche très RESTful.
OLDPASSWD
et NEWPASSWD
ne représentent rien dans votre hiérarchie de ressources et pire encore, l'opération n'est pas idempotente.
Vous ne pouvez donc utiliser que POST
comme verbe, et vous ne devez pas inclure les deux mots de passe dans votre chemin d'accès aux ressources.
Quelles sont les fonctionnalités d'une opération de réinitialisation de mot de passe?
Le point 1 ici signifie que vous ne pouvez pas utiliser GET, vous devez soit POST quelque chose représentant l'opération de changement de mot de passe vers un URI représentant une ressource qui gère les changements de mot de passe, soit PUT quelque chose représentant le nouveau mot de passe vers un URI représentant le mot de passe ou représentant quelque chose (par exemple l'utilisateur) dont ce mot de passe est une caractéristique.
En général, nous POSTONS, notamment parce que cela peut être gênant de METTRE quelque chose que nous ne pourrons PAS OBTENIR plus tard et bien sûr, nous ne pourrons PAS OBTENIR le mot de passe.
Le point 2 sera donc des données représentant le nouveau mot de passe, dans ce qui est POSTé.
Le point 3 signifie que nous devrons autoriser la demande, ce qui signifie que si l'utilisateur est l'utilisateur actuel, nous aurons besoin que le mot de passe actuel nous soit prouvé (bien que nous ne recevions pas nécessairement le mot de passe actuel, si par exemple un défi basé sur le hachage). a été utilisé pour prouver sa connaissance sans l'envoyer).
L'URI doit donc être quelque chose comme <http://example.net/changeCurrentUserPassword>
ou <http://example.net/users/joe/changePassword>
.
Nous pouvons décider que nous voulons recevoir le mot de passe actuel dans les données POST ainsi que dans le mécanisme d'autorisation général utilisé.