J'essaie toujours de trouver la meilleure solution de sécurité pour protéger REST API, car la quantité d'applications mobiles et d'API augmente chaque jour.
J'ai essayé différentes méthodes d'authentification, mais j'ai encore quelques malentendus, j'ai donc besoin des conseils de quelqu'un de plus expérimenté.
Laissez-moi vous dire comment je comprends tout ça. Si je comprends mal quelque chose, faites-le moi savoir.
En ce qui concerne REST est sans état ainsi que le WEB en général, nous devons envoyer des données d'authentification dans chaque demande (cookies, token ....). Je connais trois mécanismes largement utilisés pour authentifier l'utilisateur
Jeton avec HTTPS. J'ai souvent utilisé cette approche, elle est assez bonne avec HTTPS. Si l'utilisateur fournit un mot de passe et une connexion corrects, il recevra un jeton en réponse et l'utilisera pour les demandes ultérieures. Le jeton est généré par le serveur et stocké, par exemple dans le tableau séparé ou le même où les informations utilisateur sont stockées. Donc, pour chaque serveur de requêtes, vérifie si l'utilisateur a un jeton et c'est la même chose que dans la base de données. Tout est assez simple.
Jeton JWT. Ce jeton est auto-descriptif, il contient toutes les informations nécessaires sur le jeton lui-même, l'utilisateur ne peut pas changer par exemple la date d'expiration ou toute autre revendication, car ce jeton est généré (signé) par le serveur avec un mot-clé secret. C'est aussi clair. Mais un gros problème, personnellement pour moi, comment invalider le jeton.
OAuth 2. Je ne comprends pas pourquoi cette approche devrait être utilisée lorsque la communication est établie directement entre le serveur et le client. Pour autant que je comprends, OAuth est utilisé pour émettre un jeton avec une portée limitée pour permettre à d'autres applications d'accéder aux informations utilisateur sans stocker de mot de passe et de connexion. C'est une excellente solution pour les réseaux sociaux, lorsque l'utilisateur veut Pour vous inscrire sur une page, le serveur peut demander des autorisations pour obtenir des informations sur l'utilisateur, par exemple sur Twitter ou Facebook, et remplir les champs d'inscription avec des données utilisateur, etc.
Considérez le client mobile pour la boutique en ligne.
Première question, dois-je préférer JWT au jeton de premier type? Dans la mesure où j'ai besoin d'un utilisateur de connexion/déconnexion sur le client mobile, je dois stocker quelque part un jeton ou en cas de JWT, le jeton doit être invalidé à la déconnexion. Différentes approches sont utilisées pour invalider le jeton dont l'une consiste à créer une liste de jetons invalides (liste noire). Hmm. La table/le fichier aura une taille beaucoup plus grande que si le jeton était stocké dans la table et associé à l'utilisateur, et juste supprimé lors de la déconnexion.
Quels sont donc les avantages du jeton JWT?
Deuxième question à propos de OAuth, dois-je l'utiliser en cas de communication directe avec mon serveur? À quoi sert une couche supplémentaire entre le client et le serveur uniquement pour émettre un jeton, mais la communication ne se fera pas avec oauth server mais avec le serveur principal. Si je comprends bien OAuth server est uniquement responsable de donner aux applications tierces des autorisations (tokens) pour accéder aux informations privées des utilisateurs. Mais mon application client mobile n'est pas tierce.
Prenons le premier cas. Chaque client obtient un identifiant aléatoire qui dure pendant la durée de la session - qui peut être de plusieurs jours si vous le souhaitez. Ensuite, vous stockez les informations relatives à cette session quelque part côté serveur. Il peut s'agir d'un fichier ou d'une base de données. Supposons que vous transmettez l'ID via un cookie, mais vous pouvez utiliser l'URL ou un en-tête HTTP.
Avantages:
Inconvénients:
Dans le second cas, les données sont stockées dans un JWT qui est transmis plutôt que sur le serveur.
Avantages:
Inconvénients:
Le côté serveur a besoin de code pour générer, valider et lire les JWT. Ce n'est pas difficile mais il y a un peu de courbe d'apprentissage et la sécurité en dépend.
Quiconque obtient une copie de la clé de signature peut créer des JWT. Vous ne savez peut-être pas quand cela se produit.
Il y avait (existe?) Un bogue dans certaines bibliothèques qui acceptaient tout JWT signé avec l'algorithme "none" afin que n'importe qui puisse créer des JWT auxquels le serveur ferait confiance.
Pour révoquer un JWT avant son expiration, vous devez utiliser une liste de révocation. Cela vous ramène aux problèmes de stockage côté serveur que vous tentiez d'éviter.
Souvent OAuth est utilisé pour l'authentification (c'est-à-dire l'identité) mais il peut être utilisé pour partager d'autres données comme une liste de contenu que l'utilisateur a acheté et est autorisé à télécharger. Il peut également être utilisé pour accorder accès en écriture aux données stockées par le tiers. Vous pouvez utiliser OAuth pour authentifier les utilisateurs, puis utiliser le stockage côté serveur ou JWT pour les données de session.
Avantages:
Inconvénients:
Demandez-vous pourquoi vous devez invalider le jeton d'origine.
Un utilisateur se connecte, un jeton est généré et l'application disparaît.
L'utilisateur appuie sur déconnexion, un nouveau jeton est généré et remplace le jeton d'origine. Encore une fois, tout va bien.
Vous semblez vous inquiéter du cas où les deux jetons traînent. Que se passe-t-il si l'utilisateur se déconnecte puis fait une demande en utilisant le jeton connecté? Dans quelle mesure ce scénario est-il réaliste? Est-ce juste un problème lors de la déconnexion ou existe-t-il de nombreux scénarios possibles où plusieurs jetons peuvent être un problème?
Je ne pense pas que ça vaille la peine de s'inquiéter. Si quelqu'un intercepte et décode vos données https cryptées, vous avez des problèmes bien plus importants.
Vous pouvez vous offrir une protection supplémentaire en mettant un délai d'expiration sur le jeton d'origine. Donc, si cela finit par être volé ou quelque chose, ce ne serait bon que pour une courte période de temps.
Sinon, je pense que vous auriez besoin d'avoir des informations d'état sur le serveur. Ne mettez pas les jetons sur liste noire, mais placez-les dans la liste blanche de la signature du jeton actuel.
Vous pouvez gérer les problèmes JWT que vous avez mentionnés en stockant une valeur de sel avec l'utilisateur et en utilisant le sel comme partie du jeton pour l'utilisateur. Ensuite, lorsque vous devez invalider le jeton, changez simplement le sel.
Je sais que cela fait quelques années, mais je ferais en fait différemment maintenant. Je pense que je ferais en sorte que les jetons d'accès aient une durée de vie relativement courte, disons une heure. Je serais également sûr d'utiliser des jetons d'actualisation qui étaient avec état sur le serveur, puis lorsque je voulais mettre fin à la session de quelqu'un, je révoquerais le jeton d'actualisation en le supprimant du serveur. Ensuite, après une heure, l'utilisateur serait déconnecté et devrait se reconnecter pour retrouver l'accès.
Le serment n'est PAS un protocole d'authentification mais une norme ou un protocole d'autorisation. Donc, si vous utilisez la fonction d'ajout de calendrier Google par exemple, c'est un serment. L'application répertoriera l'API de Google pour les éléments ou les liens URL vers les différents crochets qu'elle recherche pour transmettre des informations. Si vous voulez une autorisation, alors vous voulez une connexion OIDC ou openID.
Pour votre cas d'utilisation, je recommanderais un peu de tout ce qui précède. Si vous utilisez OIDC, les informations d'identification de l'utilisateur s'authentifieraient via HTTPS auprès d'un serveur d'authentification. À l'intérieur de la demande, il y aurait le nom d'utilisateur et le mot de passe de l'utilisateur ainsi que l'ID unique (client) généré aléatoirement de l'application. Si les informations d'identification sont valides et que l'ID client est valide, le serveur répond avec un mot de passe à usage unique. L'application utilisateur prend ensuite ce mot de passe et le transmet au service Web. Le service Web retransmet le mot de passe au serveur d'authentification pour valider que le mot de passe est légitime. Si tel est le cas, le serveur d'authentification répondra au service Web avec un jeton d'autorisation/d'accès (AK). Vous pouvez désormais adopter l'une des deux approches suivantes:
2.1 Vous pouvez stocker ce jeton dans votre application client en tant que jeton d'accès. Demandez ensuite au service Web de répondre avec un jeton d'actualisation. Le jeton d'autorisation pourrait avoir une durée de vie de quelques heures ou jours et le jeton d'actualisation aurait une durée de vie plus courte. Vous devez utiliser un JWT pour le jeton d'actualisation, mais vous pouvez utiliser une chaîne plus petite générée aléatoirement comme jeton d'actualisation. De cette façon, vous n'avez pas nécessairement à passer l'AK à chaque demande. Si, disons, 5 minutes s'écoulent et que le serveur ne reçoit pas de jeton d'actualisation de l'utilisateur, il déconnecte l'utilisateur et invalide tous les jetons (AK et actualisation). Le seul inconvénient ici est que si l'AK est compromis, vous risquez que la saison des utilisateurs soit détournée.
2.2 (le plus recommandé) le jeton d'accès et l'autorisation ensemble sont généralement les mêmes mais peuvent techniquement être deux jetons différents. C'est très bien si l'utilisateur s'est déjà authentifié et que vous utilisez son empreinte digitale ou son ID de visage via l'API matérielle du système d'exploitation du téléphone. Si le téléphone dit oui, c'est lui ou elle, il vous suffit d'envoyer l'ID client pour accéder à un stockage/dépôt de clés via une passerelle API sans informations d'identification. La passerelle répondrait avec votre jeton d'authentification que vous avez généré précédemment. L'application peut ensuite envoyer ce jeton au service Web et le service Web répondrait par un jeton d'accès et un jeton d'actualisation. Vous pouvez ensuite supprimer le jeton d'authentification et conserver le jeton d'accès et d'actualisation.
L'idée ici est qu'après que l'utilisateur s'est authentifié pour la première fois et que le jeton d'authentification est généré, il peut avoir une durée de vie de 3 mois. Maintenant, vous ne voulez pas garder cela sur votre téléphone client, car s'il est compromis, l'utilisateur est foutu. Par conséquent, pourquoi le conserver dans un magasin de clés et non sur le téléphone. Désormais, le jeton d'accès auquel répond le service Web peut avoir une durée de vie d'une heure et le jeton d'actualisation aurait une durée de vie de 5 minutes. Tant que le jeton d'actualisation est en jeu, la session reste active. Lorsque vous arrêtez de recevoir ce jeton d'actualisation, vous invalidez le jeton d'actualisation et d'accès, tuez la session et vous pouvez toujours conserver le jeton d'authentification. Votre autorisation devrait alors être un JWT avec l'algorithme ES-256. Votre jeton d'accès devrait ou pourrait utiliser RS-256 et votre jeton d'actualisation pourrait utiliser HS-256. Ne pas utiliser RS & ES de chiffrement asymétrique, ce qui signifie que vous avez besoin d'une clé publique et d'une clé privée pour le générer. Alors que HS utilise un cryptage symétrique, ce qui signifie qu'un seul mot de passe ou clé est utilisé pour le générer.