Meilleures pratiques pour générer des jetons OAuth?

100

Je me rends compte que la spécification OAuth ne spécifie rien sur l'origine du code ConsumerKey, ConsumerSecret, AccessToken, RequestToken, TokenSecret ou Verifier, mais je suis curieux de savoir s'il existe des meilleures pratiques pour créer des jetons considérablement sécurisés (en particulier Token / Combinaisons secrètes).

Comme je le vois, il existe quelques approches pour créer les jetons:

  1. Utilisez simplement des octets aléatoires, stockez dans la base de données associée au consommateur / utilisateur
  2. Hash certaines données spécifiques à l'utilisateur / consommateur, stocker dans la base de données associée au consommateur / utilisateur
  3. Crypter les données spécifiques aux utilisateurs / consommateurs

Les avantages de (1) sont que la base de données est la seule source d'informations qui semble la plus sûre. Il serait plus difficile de lancer une attaque contre (2) ou (3).

Le hachage de données réelles (2) permettrait de régénérer le jeton à partir de données probablement déjà connues. Peut ne pas vraiment fournir d'avantages à (1) car il faudrait de toute façon stocker / rechercher. Plus gourmand en CPU que (1).

Crypter des données réelles (3) permettrait de décoder des informations. Cela nécessiterait moins de stockage et potentiellement moins de recherches que (1) et (2), mais potentiellement moins sécurisé également.

Y a-t-il d'autres approches / avantages / inconvénients à considérer?

EDIT: une autre considération est qu'il DOIT y avoir une sorte de valeur aléatoire dans les jetons car il doit exister la capacité d'expirer et de réémettre de nouveaux jetons, de sorte qu'ils ne doivent pas être uniquement composés de données réelles.

Suivez les questions :

Existe-t-il une longueur minimale de jeton pour assurer une sécurité cryptographique significative? Si je comprends bien, des secrets de jeton plus longs créeraient des signatures plus sécurisées. Cette compréhension est-elle correcte?

Y a-t-il des avantages à utiliser un encodage particulier par rapport à un autre du point de vue du hachage? Par exemple, je vois beaucoup d'API utilisant des encodages hexadécimaux (par exemple des chaînes GUID). Dans l'algorithme de signature OAuth, le jeton est utilisé sous forme de chaîne. Avec une chaîne hexadécimale, le jeu de caractères disponible serait beaucoup plus petit (plus prévisible) qu'avec un encodage Base64. Il me semble que pour deux chaînes de longueur égale, celle avec le plus grand jeu de caractères aurait une distribution de hachage meilleure / plus large. Cela me semble que cela améliorerait la sécurité. Cette hypothèse est-elle correcte?

La spécification OAuth soulève ce problème même dans 11.10 Entropy of Secrets .

Mckamey
la source
Pourquoi le cryptage? Le hachage n'est-il pas assez bon? Si le simple hachage est suffisant pour le mot de passe, ne devrait-il pas être encore meilleur pour des jetons d'accès plus longs?
AlikElzin-kilaka
Cela fait 7,5 ans que j'ai posé la question. Je ne m'en souviens honnêtement pas.
mckamey
1
En relisant, le hachage et le cryptage étaient deux approches différentes suggérées. Le chiffrement permettrait au serveur d'obtenir des informations sans recherche de base de données. C'était un compromis parmi tant d'autres.
mckamey

Réponses:

93

OAuth ne dit rien sur le jeton, sauf qu'il a un secret qui lui est associé. Donc, tous les programmes que vous avez mentionnés fonctionneraient. Notre jeton a évolué à mesure que les sites s'agrandissaient. Voici les versions que nous utilisions auparavant,

  1. Notre premier jeton est un BLOB chiffré avec nom d'utilisateur, secret de jeton et expiration, etc. Le problème est que nous ne pouvons pas révoquer les jetons sans aucun enregistrement sur l'hôte.

  2. Nous l'avons donc changé pour tout stocker dans la base de données et le jeton est simplement un nombre aléatoire utilisé comme clé de la base de données. Il a un index de nom d'utilisateur, il est donc facile de répertorier tous les jetons d'un utilisateur et de le révoquer.

  3. Nous avons assez peu d'activités de piratage. Avec un nombre aléatoire, nous devons aller dans la base de données pour savoir si le jeton est valide. Nous sommes donc retournés au BLOB chiffré. Cette fois, le jeton ne contient que la valeur chiffrée de la clé et l'expiration. Nous pouvons donc détecter les jetons invalides ou expirés sans accéder à la base de données.

Quelques détails d'implémentation qui peuvent vous aider,

  1. Ajoutez une version dans le jeton afin de pouvoir modifier le format du jeton sans casser les existants. Tous nos jetons ont le premier octet comme version.
  2. Utilisez la version de base64 sécurisée pour les URL pour encoder le BLOB afin de ne pas avoir à gérer les problèmes d'encodage d'URL, ce qui rend le débogage plus difficile avec la signature OAuth, car vous pouvez voir une chaîne de base à triple encodage.
Codeur ZZ
la source
2
Excellent, merci. L'idée de version est bonne. J'ai la base64 conviviale pour les URL, mais j'aimerais avoir un encodage strictement alphanumérique pour une lecture encore plus facile.
mckamey
Je n'avais pas pensé à ça avant, très intéressant! Je prévoyais d'utiliser la mise en cache des clés APC pour garder une charge inutile de la base de données avant de lire ceci. Toujours pas sûr que cela ne soit pas beaucoup plus lent qu'une recherche de mémoire partagée APC (au moins sur la 2ème, 3ème, etc ... demande dans un délai raisonnable).
Philzen