REST API security Jeton stocké vs JWT vs OAuth

104

J'essaie toujours de trouver la meilleure solution de sécurité pour protéger les API REST, car le nombre d'applications mobiles et d'API augmente chaque jour.

J'ai essayé différentes méthodes d'authentification, mais il y a toujours des 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 quelque chose de mal, s'il vous plaît faites le moi savoir.

Dans la mesure où l'API REST est sans état, de même que WEB en général, nous devons envoyer des données d'authentification dans chaque demande (cookies, jeton, etc.). Je connais trois mécanismes largement utilisés pour authentifier l'utilisateur

  1. Jeton avec HTTPS. J'ai souvent utilisé cette approche 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 la table séparée ou de la même manière que les informations utilisateur sont stockées. Donc, pour chaque requête, le serveur vérifie si l'utilisateur a un jeton et qu'il est identique à celui de la base de données. Tout est assez simple.

  2. JWT Token. Ce jeton est auto-descriptif, il contient toutes les informations nécessaires sur le jeton lui-même. L'utilisateur ne peut pas modifier, par exemple, la date d'expiration ou toute autre revendication, car ce jeton est généré (signé) par le serveur avec le mot clé secret. Ceci est également clair. Mais un gros problème, personnellement pour moi, comment invalider un jeton.

  3. 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. Autant que je sache, le serveur OAuth est utilisé pour émettre un jeton avec une portée restreinte afin de permettre à d'autres applications d'accéder aux informations utilisateur sans stocker de mot de passe ni de connexion. C'est une excellente solution pour les réseaux sociaux. Lorsque l'utilisateur souhaite s'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'enregistrement avec les données de l'utilisateur, etc.

Envisagez le client mobile pour la boutique en ligne.

Première question devrais-je préférer JWT au premier jeton de type? Dans la mesure où j'ai besoin de connexion / déconnexion d'un utilisateur sur un client mobile, je dois stocker un jeton quelque part ou, en cas de JWT, un jeton doit être invalidé à la déconnexion. Différentes approches sont utilisées pour invalider le jeton. L’une des méthodes consiste à créer une liste de jetons non valide (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 simplement supprimé lors de la déconnexion.

Alors, quels sont les avantages du jeton JWT?

Deuxième question sur OAuth, devrais-je l'utiliser en cas de communication directe avec mon serveur? A quoi sert une couche supplémentaire entre le client et le serveur pour émettre un jeton, mais la communication ne se fera pas avec oauth server mais avec le serveur principal. Si je comprends bien, le serveur OAuth n’est responsable que de donner aux tiers des autorisations (jetons) d’accéder aux informations personnelles de l’utilisateur. Mais mon application client mobile n'est pas une tierce partie.

CROSP
la source
Merci, je me demandais cela récemment. Je suis allé avec la gestion de session (Beaker), et supprimer les jetons de session après une heure. Oauth ne semblait pas la bonne.
JasTonAChair

Réponses:

86

Considérons le premier cas. Chaque client reçoit un identifiant aléatoire qui dure toute la durée de la session, ce qui peut prendre plusieurs jours si vous le souhaitez. Ensuite, vous stockez les informations pertinentes pour cette session quelque part côté serveur. Cela pourrait être dans un fichier ou une base de données. Supposons que vous transmettiez l'ID via un cookie, mais que vous puissiez utiliser l'URL ou un en-tête HTTP.

ID de session / Cookies

Avantages:

  • Facile à coder le client et le serveur.
  • Facile de détruire une session lorsque quelqu'un se déconnecte.

Les inconvénients:

  • Le côté serveur doit périodiquement supprimer les sessions expirées pour lesquelles le client ne s'est pas déconnecté.
  • Chaque demande HTTP nécessite une recherche dans le magasin de données.
  • Les besoins en stockage augmentent à mesure que de plus en plus d'utilisateurs ont des sessions actives.
  • S'il existe plusieurs serveurs HTTP frontaux, les données de session stockées doivent être accessibles à tous. Cela pourrait être un peu plus de travail que de le stocker sur un serveur. Les problèmes les plus importants sont que le magasin de données devient un point de défaillance unique et peut devenir un goulot d'étranglement.

Jetons Web JSON (JWT)

Dans le second cas, les données sont stockées dans un fichier JWT qui est transmis plutôt que sur le serveur.

Avantages:

  • Les problèmes de stockage côté serveur ont disparu.
  • Le code côté client est facile.

Les inconvénients:

  • La taille de JWT peut être supérieure à un identifiant de session. Cela pourrait affecter les performances du réseau car il est inclus avec chaque requête HTTP.
  • Les données stockées dans le JWT sont lisibles par le client. Cela peut être un problème.
  • Le côté serveur a besoin de code pour générer, valider et lire les fichiers JWT. Ce n'est pas difficile, mais il y a un peu de courbe d'apprentissage et la sécurité en dépend.

    Toute personne qui obtient une copie de la clé de signature peut créer des fichiers JWT. Vous pourriez ne pas savoir quand cela se produit.

    Il y avait (est?) Un bogue dans certaines bibliothèques qui acceptaient n'importe quel JWT signé avec l'algorithme "none" afin que tout le monde puisse créer des JWT auxquels le serveur aurait 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.

OAuth

Souvent, OAuth est utilisé pour l'authentification (identité), mais il peut également être utilisé pour partager d'autres données, par exemple une liste de contenu que l'utilisateur a acheté et qu'il est autorisé à télécharger. Il peut également être utilisé pour accorder un 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:

  • Aucun code permettant aux utilisateurs de s'inscrire ou de réinitialiser leur mot de passe.
  • Aucun code pour envoyer un email avec un lien de validation, puis valider l'adresse.
  • Les utilisateurs n'ont pas besoin de connaître / écrire un autre nom d'utilisateur et mot de passe.

Les inconvénients:

  • Vous dépendez du tiers pour que vos utilisateurs utilisent votre service. Si leur service tombe en panne ou s’ils l’interrompent, vous devez trouver quelque chose d’autre. Exemple: comment migrer les données de compte de l'utilisateur si son identité change de "[email protected]" à "[email protected]"?
  • Généralement, vous devez écrire du code pour chaque fournisseur. par exemple Google, Facebook, Twitter.
  • Vous ou vos utilisateurs pourriez avoir des problèmes de confidentialité. Les fournisseurs savent quels utilisateurs utilisent votre service.
  • Vous faites confiance au fournisseur. Il est possible pour un fournisseur d’émettre des jetons valables d’un utilisateur à un autre. Cela pourrait être à des fins légales ou non.

Divers

  • Les identifiants de session et les JWT peuvent être copiés et utilisés par plusieurs utilisateurs. Vous pouvez stocker l'adresse IP du client dans un fichier JWT et la valider, mais cela empêche les clients de passer du Wi-Fi au cellulaire, par exemple.
Chad Clark
la source
Pour ajouter à votre réponse, oAuth peut ne pas être utile lorsqu'un utilisateur souhaite s'inscrire en utilisant les comptes de leur entreprise qui ne sont généralement pas associés à aucun des sites Web de réseaux sociaux ou de Google.
Aftab Naveed
5
Je ne sais pas pourquoi c'est la réponse acceptée? il ne répond pas à la vraie question, mais reformule la question d'une autre manière
amd
1
Vous dites: "Les données stockées dans le JWT sont lisibles par le client. Cela peut être un problème. Pourquoi ne pas utiliser JWE si c'est un problème?
Argent le
Cette réponse confond les pommes et les oranges. Ne les comparez pas avec OAuth 2.0 (la spécification "autorisation"). Ce que l'OP doit savoir, c'est: "Flux de mots de passe du propriétaire de la ressource" - ce qui constitue une authentification en tant qu'attribution.
Onur Yıldırım
5

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é? À quel point 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 cela 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 donner une protection supplémentaire en définissant un délai d'expiration sur le jeton d'origine. Donc, si on finit par être volé ou quelque chose du genre, ce ne serait bon que pour une courte période.

Sinon, je pense que vous auriez besoin d'informations d'état sur le serveur. Ne mettez pas les jetons sur la liste noire, mais plutôt sur la liste blanche la signature du jeton actuel.

Cerad
la source
2
Si vous supposez que certains de vos clients sont malveillants, il est facile de voir qu’une session sera copiée et réutilisée et vous devez le contrer sur le serveur.
Michael Shaw
1
Mauvaise idée, cela peut être utilisé plus tard par les hackers, ou simplement forcé ...
CROSP
2
Imaginez qu'un utilisateur veuille se déconnecter de tous les autres appareils, l'utilisation de JWT n'est pas possible.
amd
@amd pas possible? Que faire si j'ajoute nonce = (aléatoire) et si l'utilisateur se déconnecte, remplace le nonce. Cela semble simple et efficace.
Simon B.
3

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 en tant que 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 le ferais différemment maintenant. Je pense que je veillerais à ce que les jetons d'accès aient une durée de vie relativement courte, disons une heure. Je m'assurerais également d'utiliser des jetons d'actualisation avec état sur le serveur, puis, lorsque je souhaitais mettre fin à la session de quelqu'un, je révoquais le jeton d'actualisation en le supprimant du serveur. Ensuite, au bout d'une heure, l'utilisateur serait déconnecté et devrait se reconnecter pour pouvoir y accéder à nouveau.

RibaldEddie
la source
4
Mais encore une fois, dans ce cas, il devient
saturé
2
Vous pouvez également invalider en fonction du temps.
RibaldEddie
Quelle est la différence entre l'heure d'expiration dans ce cas? Comment puis-je invalider un jeton en fonction du temps lorsque l'utilisateur souhaite se déconnecter du client mobile? Il semble qu'il n'y ait aucun moyen que l'API soit apatride dans ce cas. Quelle est la solution la plus appropriée et la plus sécurisée?
CROSP
2
La meilleure solution pour vous déconnecter d'un seul périphérique consiste à vous assurer que vous utilisez un ID client en plus du sel. Je vous suggère de consulter la spécification de jeton porteur Oauth-jwt pour mieux comprendre.
RibaldEddie
Merci pour la réponse, mais je ne comprends pas pourquoi devrais-je utiliser OAuth dans ce cas du tout.
CROSP