Je travaille sur une API pour un service REST que je vais à la fois produire et consommer. J'ai passé ces derniers jours à essayer de comprendre comment gérer correctement l'authentification, et je pense que j'ai finalement trouvé quelque chose.
Je viens avec cela sur la base des faits suivants sur la pile d'applications:
- Le client et le serveur sont en .NET4 (partie client dans le profil client)
- Le serveur expose à l'aide de WCF REST
- Je ne veux vraiment pas garder le nom d'utilisateur et le mot de passe en mémoire dans l'application
À partir de 3, je voulais utiliser une forme d'authentification par jeton, afin qu'après vérification des informations d'identification par le serveur, le client récupère un jeton à utiliser dans le reste de l'application (cela me permettra de faire d'autres choses, telles que temporisation des utilisateurs, possibilité de déplacer les utilisateurs de manière transparente entre les versions Web et de bureau, etc.). Après avoir compris comment rendre les appels rejouables et inviolables, j'ai trouvé ce qui suit:
- Avant que le client ne tente de s'authentifier, il génère une paire de clés Diffie-Hellman à l'aide de la
ECDiffieHellmanCng
classe. - Il envoie la partie publique de la paire de clés sur le câble avec le nom d'utilisateur et le mot de passe (via HTTPS bien sûr).
- Le serveur authentifie la combinaison nom d'utilisateur / mot de passe. En cas de succès, il procède ensuite comme suit:
- Crée un jeton de session unique
- Génère sa propre paire de clés DH et calcule le secret partagé à partir de la clé publique fournie par le client
- Prend note du jeton de session, du secret partagé, de l'utilisateur et de l'heure de la "dernière action" (utilisée pour une fenêtre d'expiration continue) dans sa base de données
- Renvoie le jeton de session, sa clé DH publique et un message de réussite d'authentification
- Le client prend la clé DH de la réponse, calcule le secret partagé et stocke le jeton et le secret en mémoire.
À partir de ce moment, la combinaison jeton / secret de session fonctionne comme la plupart des autres API REST, la demande étant empreinte digitale et horodatée, puis une sorte de HMAC est générée. Chaque fois qu'un client exécute une action contre le serveur, il vérifie la paire jeton / secret, autorise l'action si elle est valide et non expirée, et met à jour le dernier enregistrement d'action de la session.
Je ne vois pas de défauts évidents et est probablement trop conçu pour cela, mais je dois apprendre à le faire à un moment donné. Le HMAC empêche les attaques de rejeu, la négociation DH aide à prévenir les attaques MITM (je ne peux pas penser à une attaque réalisable du haut de ma tête entre HMAC / DH).
Des trous que n'importe qui peut percer?