web-dev-qa-db-fra.com

Authentification basée sur les jetons - Sécurisation du jeton

J'ai développé un backend REST pour une application mobile et je cherche maintenant à implémenter une authentification basée sur des jetons pour éviter d'avoir à inviter l'utilisateur à se connecter à chaque exécution de l'application.

Ce que j'avais à l'esprit était sur la demande initiale que l'utilisateur envoie ses informations d'identification à l'aide de l'authentification de base sur SSL. Une fois que le serveur authentifie les informations d'identification, il crée un jeton sécurisé et le renvoie à l'utilisateur afin qu'il puisse l'utiliser dans les demandes suivantes jusqu'à ce que le jeton expire ou soit révoqué.

Je cherche des conseils sur la façon de générer un jeton qui ne sera pas sensible à des choses comme les attaques MoM/Replay ainsi que de m'assurer que les données stockées dans le jeton ne peuvent pas être extraites.

Je vais utiliser ce qui suit approche pour générer le jeton qui, je pense, empêcherait d'extraire des données de celui-ci. Cependant, je dois encore m'assurer qu'il n'est pas vulnérable aux autres attaques.

L'API ne sera accessible que via SSL, mais je ne suis pas sûr de pouvoir compter uniquement sur cela d'un point de vue de la sécurité.

99
James

Le "jeton d'authentification" fonctionne selon la façon dont le serveur s'en souvient.

Un jeton générique est une chaîne aléatoire; le serveur conserve dans sa base de données un mappage des jetons émis aux noms d'utilisateurs authentifiés. Les anciens jetons peuvent être supprimés automatiquement afin d'empêcher la base de données du serveur de croître indéfiniment. Un tel jeton est suffisamment bon pour la sécurité tant qu'un attaquant ne peut pas créer un jeton valide avec une probabilité non négligeable, un "jeton valide" étant "un jeton qui se trouve dans la base de données des jetons émis". Il est suffisant que les valeurs des jetons aient une longueur d'au moins 16 octets et soient produites avec une cryptographie forte PRNG (par exemple /dev/urandom, CryptGenRandom(), Java.security.SecureRandom ... selon votre plateforme).

Il est possible de décharger l'exigence de stockage sur les clients eux-mêmes. Dans le paragraphe ci-dessus, quelle "mémoire" le serveur doit-il avoir d'un token? À savoir le nom d'utilisateur et la date de production du jeton. Alors, créez vos jetons comme ceci:

  • Le serveur a une clé secrète [~ # ~] k [~ # ~] (une séquence de, disons, 128 bits, produite par un PRNG cryptographiquement sécurisé ).
  • Un jeton contient le nom d'utilisateur ( [~ # ~] u [~ # ~] ), l'heure d'émission (( [~ # ~] t [~ # ~] ), et un contrôle d'intégrité à clé calculé sur [~ # ~] u [~ # ~] et [~ # ~] t [~ # ~] (ensemble) , saisi avec [~ # ~] k [~ # ~] (par défaut, utilisez HMAC avec SHA-256 ou SHA-1).

Grâce à sa connaissance de [~ # ~] k [~ # ~] , le serveur peut vérifier qu'un jeton donné, renvoyé par l'utilisateur, est l'un des siens ou non; mais l'attaquant ne peut pas forger de tels jetons.

La réponse à laquelle vous liez ressemble un peu à cela, sauf qu'elle parle de cryptage au lieu de MAC, et c'est:

  1. confus;
  2. déroutant;
  3. potentiellement précaire;

parce que le chiffrement n'est pas MAC.

82
Thomas Pornin

En bref, vous devez utiliser un jeton aléatoire unique de force cryptographique et le hacher dans la base de données.

Le jeton

  • ne doit être utilisé qu'une seule fois,
  • ne doit être utilisable que pour l'utilisateur pour lequel il a été créé,
  • doit être envoyé uniquement via HTTPS,
  • devrait avoir une date d'expiration (par exemple 7 jours).

Une fois que l'utilisateur se connecte avec le jeton, il n'est pas valide et un nouveau jeton doit être créé et donné à l'utilisateur. Dans le cas d'un jeton expiré, l'utilisateur doit être obligé de se reconnecter à l'aide de ses véritables informations d'identification.

Une description plus définitive et plus longue de ces règles se trouve dans la partie 2 de The Definitive Guide to Forms based Site Authentication :

Les cookies de connexion persistants (fonctionnalité "se souvenir de moi") sont une zone de danger; d'une part, ils sont entièrement aussi sûrs que les connexions conventionnelles lorsque les utilisateurs savent comment les gérer; et d'autre part, ils représentent un énorme risque pour la sécurité de la plupart des utilisateurs, qui les utilisent sur des ordinateurs publics, oublient de se déconnecter, ne savent pas ce que sont les cookies ou comment les supprimer, etc.

[...]

Suivez article "Meilleures pratiques" de Charles Miller . Ne soyez pas tenté de suivre les meilleures pratiques "améliorées" liées à la fin de son article. Malheureusement, les "améliorations" du système sont facilement contrecarrées (tout ce qu'un attaquant a à faire lors du vol du cookie "amélioré" doit se rappeler de supprimer l'ancien. Cela obligera l'utilisateur légitime à se reconnecter, créant un nouvel identifiant de série et en laissant le volé valide).

Et NE PAS STOCKER LE COOKIE DE CONNEXION PERSISTANT (JETON) DANS VOTRE BASE DE DONNÉES, SEULEMENT UN HASH OF IT! Le jeton de connexion est équivalent au mot de passe, donc si un attaquant a mis la main sur votre base de données, il pourrait utiliser les jetons pour se connecter à n'importe quel compte, tout comme s'il s'agissait de combinaisons login-mot de passe en texte clair. Par conséquent, utilisez un hachage fortement salé (bcrypt/phpass) lors du stockage de jetons de connexion persistants.


Mise à jour: Désolé, j'ai mal compris la question. La méthode que vous avez liée semble raisonnable, mais elle ne vous protégera pas des attaques de rejeu ou de l'homme du milieu. Vous devez utiliser SSL à côté.

38
Polynomial

Un service Web API RESTful pur doit utiliser les fonctionnalités standard du protocole sous-jacent:

  1. Pour HTTP, l'API RESTful doit englober et se conformer aux en-têtes, codes d'état et méthodes HTTP existants. L'ajout d'un nouvel en-tête HTTP viole les principes REST.

  2. Les services RESTful DOIVENT ÊTRE SANS ÉTAT. Toutes les astuces, telles que l'authentification basée sur des jetons qui tente de se souvenir de l'état des requêtes REST précédentes sur le serveur, viole les principes REST).

Conclusion: à des fins d'authentification/autorisation, vous devez utiliser l'en-tête d'autorisation HTTP. Et vous devez ajouter l'en-tête du schéma d'autorisation HTTP spécifique dans chaque demande ultérieure qui doit être authentifiée.

J'ai développé un service Web RESTful pour l'application Cisco Prime Performance Manager. Recherchez dans Google le Cisco Prime Performance Manager REST API document que j'ai écrit pour cette application pour plus de détails sur la conformité de l'API RESTFul - voir ci-dessous. Pour cette application, nous avons choisi d'utiliser le HTTP "Basic" "Schéma d'autorisation pour authentifier et autoriser les requêtes. Et évidemment, nous utilisons HTTP pour crypter toutes les données en transit du client vers le serveur lors de l'utilisation de l'autorisation HTTP.

http://www.Cisco.com/c/en/us/support/cloud-systems-management/prime-performance-manager/products-programming-reference-guides-list.html

4
Rubens Gomes