Oauthlib: Client_secret et code_verifier (PKCE) doivent être transmis en toute sécurité

Créé le 19 avr. 2019  ·  19Commentaires  ·  Source: oauthlib/oauthlib

client_secret et code_verifier sont acceptés lorsqu'ils sont envoyés en tant que paramètres dans la chaîne de requête

Request.client_secret doit être vérifié pour la présence dans les en-têtes ou le corps et Request.code_verifier juste dans le corps mais pas dans la chaîne de requête car il s'agit de données sensibles.
Des vérifications supplémentaires peuvent être effectuées, par exemple le type de demande est POST et les données ont été envoyées à l'aide de HTTPS .

Lorsque client_secret ou code_verifier est envoyé dans la chaîne de requête, cela devrait entraîner une mauvaise demande, obligeant le client à envoyer des données en toute sécurité.

Bug Contributor Friendly OAuth2-Provider

Commentaire le plus utile

Salut @polamayster , tu as parfaitement raison.

J'ajoute les sections de RFC spécifiant comment il doit être mis en œuvre :

Section de la RFC OAuth2.0 :

https://tools.ietf.org/html/rfc6749#section -2.3.1

2.3.1.  Client Password
   Clients in possession of a client password
   MAY use the HTTP Basic authentication scheme (..) 

   Alternatively, the authorization server
   MAY support including the client credentials in the request-body (..)

   The parameters can only be transmitted in the request-body and
   MUST NOT be included in the request URI.

Section de la RFC PKCE :

https://tools.ietf.org/html/rfc7636#section -4.5

4.5.  Client Sends the Authorization Code and the Code Verifier to the
      Token Endpoint
    In addition to the parameters defined in the OAuth 2.0 Access
    Token Request (Section 4.1.3 of [RFC6749]), it sends the following parameter:

   code_verifier
      REQUIRED.  Code verifier

https://tools.ietf.org/html/rfc6749#section -4.1.3


4.1.3.  Access Token Request

   The client makes a request to the token endpoint by sending the
   following parameters (..) in the HTTP request entity-body:

Je n'ai donc aucun doute sur la pertinence de la question. Tous les PR sont les bienvenus !

Tous les 19 commentaires

Salut @polamayster , tu as parfaitement raison.

J'ajoute les sections de RFC spécifiant comment il doit être mis en œuvre :

Section de la RFC OAuth2.0 :

https://tools.ietf.org/html/rfc6749#section -2.3.1

2.3.1.  Client Password
   Clients in possession of a client password
   MAY use the HTTP Basic authentication scheme (..) 

   Alternatively, the authorization server
   MAY support including the client credentials in the request-body (..)

   The parameters can only be transmitted in the request-body and
   MUST NOT be included in the request URI.

Section de la RFC PKCE :

https://tools.ietf.org/html/rfc7636#section -4.5

4.5.  Client Sends the Authorization Code and the Code Verifier to the
      Token Endpoint
    In addition to the parameters defined in the OAuth 2.0 Access
    Token Request (Section 4.1.3 of [RFC6749]), it sends the following parameter:

   code_verifier
      REQUIRED.  Code verifier

https://tools.ietf.org/html/rfc6749#section -4.1.3


4.1.3.  Access Token Request

   The client makes a request to the token endpoint by sending the
   following parameters (..) in the HTTP request entity-body:

Je n'ai donc aucun doute sur la pertinence de la question. Tous les PR sont les bienvenus !

Je serai intéressé à assumer cela. Soumettra bientôt une demande de tirage.

Ce comportement doit-il être appliqué uniquement pour les demandes qui attendent des informations d'identification ou pour toute demande en général ?

Pour ma compréhension oauthlib.common.Request classe a un __getattr__ méthode et _params dictionnaire (mise à jour de la chaîne de requête et les paramètres du corps) et toute demande qui tente d'accéder / get client_secret ou code_verifier ne doit rechercher que dans le corps et/ou les en-têtes (il serait peut-être logique d'avoir une propriété distincte pour la recherche de données sensibles)

Je vois, je vais soumettre un pr pour cela aujourd'hui

Le samedi 20 avril 2019, à 12 h 38, Bohdan < [email protected] a écrit :

À ma connaissance, la classe oauthlib.common.Request a un __getattr__
méthode et dictionnaire _params (mis à jour à partir de la chaîne de requête et du corps
paramètres) et toute demande qui tente d'accéder/d'obtenir client_secret ou
code_verifier ne doit rechercher que dans le corps et/ou les en-têtes (peut-être en ayant
une propriété distincte pour la recherche de données sensibles aurait du sens)

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/oauthlib/oauthlib/issues/666#issuecomment-485157051 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/ABKEVQNFJUFGDB5X24JBOJDPRNWKBANCNFSM4HHD7NNQ
.

Pour ma compréhension oauthlib.common.Request classe a un __getattr__ méthode et _params dictionnaire (mise à jour de la chaîne de requête et les paramètres du corps) et toute demande qui tente d'accéder / get client_secret ou code_verifier ne doit rechercher que dans le corps et/ou les en-têtes (il serait peut-être logique d'avoir une propriété distincte pour la recherche de données sensibles)

Ainsi, les vérifications devraient avoir lieu au moment de l'accès aux attributs plutôt qu'au moment où l'URL est définie ? Si les attributs de requête ne sont définis qu'une seule fois lors de l'initialisation, nous pouvons effectuer les vérifications immédiatement au lieu de chaque accès aux attributs. Faites-moi savoir si vous pensez que nous devrions toujours effectuer les vérifications à chaque accès d'attribut.

Je me rends compte que ce problème est plus important et s'applique à l'ensemble du point /token terminaison

Je pense que le critère d'introspection est également admissible. IIRC, selon
Spécifications HTTP, les requêtes POST doivent toujours ignorer les paramètres de requête. Si
nous appliquons cela, nous résolvons automatiquement tous les problèmes sans affecter
cas d'utilisation valides. Je ne sais pas comment les autres verbes HTTP sont censés se comporter
mais je suis assez sûr sur POST one. Quelqu'un peut-il confirmer si c'est le bon
direction vers laquelle aller ?

>

Refuser tous les paramètres de requête pour tous les POST est un joli raccourci qui est attrayant ! Cependant, je m'inquiète du ResourceEndpoint d'oauthlib et du fait que certains utilisateurs peuvent toujours ajouter des arguments de requête à l'URL (bien que ce ne soit pas recommandé, c'est toujours possible techniquement).

Pouvez-vous élaborer un peu plus sur vos préoccupations concernant le point de terminaison des ressources ?

La façon dont je le vois, les demandes POST sont effectuées soit via des soumissions de formulaires, soit via une API
appels (écriture de code explicite). Je ne vois pas pourquoi quelqu'un ajouterait partiel
données en tant que paramètres de requête et partielles en tant que données de publication. En fait, il est plus facile de
s'engager complètement dans l'un ou l'autre.
En fait, si vous utilisez une bibliothèque pour faire des requêtes, il est beaucoup plus facile de
ajoutez tout comme corps de message au lieu de diviser les choses.

Les utilisateurs ajoutant des paramètres de requête à POST s'ils présentent une erreur explicative,
devrait être capable de s'auto-corriger rapidement.

Ou peut-être pouvons-nous créer un mixin ou un décorateur qui, une fois appliqué, augmenterait
erreurs pour les requêtes POST avec les paramètres de requête.

Voici une autre solution possible pour cela. Pour les points de terminaison ( AuthorizationEndpoint , IntrospectEndpoint , RevocationEndpoint ); Si la méthode de requête est POST nous pouvons ajouter la vérification des paramètres de requête dans leurs méthodes de validation de requête respectives. Pour ( TokenEndpoint , MetadataEndpoint ), nous pouvons ajouter les méthodes de génération de réponse d'enregistrement.
OU nous pouvons ajouter le mécanisme de vérification à l'intérieur de la méthode de génération de réponse de tous, par souci de cohérence. Cela vous semble-t-il une bonne idée ?

Je pense qu'il est préférable d'utiliser les méthodes de validation _request_.
Sachant que POST est uniquement pour TokenEndpoint , IntrospectEndpoint et RevocationEndpoint . Les autres sont GET : AuthorizationEndpoint , MetadataEndpoint .

Un commentaire général cependant : devrions-nous nous concentrer sur les champs sensibles (par exemple, maintenir une liste noire) ou devrions-nous refuser tous les paramètres OAuth2 (nous voulons que NONE soit dans l'URI de la requête, n'est-ce pas ?)

Idéalement, je voudrais NONE dans l'URI de la requête. Je suis allé pour une liste noire parce que je n'étais pas
sûr si je pourrais casser certains cas d'utilisation existants. Non seulement aucun OAuth2
paramètres autorisés, mais aucun paramètre de requête n'est autorisé.

>

Si vous déplacez les contrôles de la demande vers les points de terminaison, je ne vois aucun problème à désactiver tous les paramètres de requête pour ces points de terminaison !

Très bien, je vais désactiver tous les paramètres de requête sur ces points de terminaison exacts. Et
nous limitons également la méthode http à POST, n'est-ce pas ?

Bien que je comprenne le raisonnement de ce changement, cela semble être un changement décisif pour les clients qui envoient client_secret tant que paramètre de requête. Je me serais attendu à une rétrocompatibilité ou à une modification majeure de la version. Ce comportement est-il intentionnel ?

Nous utilisons actuellement django-oauth-toolkit et les clients envoient username , password , client_secret , client_id et grant_type comme requête paramètre. S'ils passent à l'envoi de tout en tant que paramètre POST , ils obtiennent l'erreur unsupported_grant_type .

La prise en charge de la requête pour POST est plus un effet secondaire que le comportement souhaité. Je comprends que cela brise votre client, donc je suggérerais d'identifier à <3.1
En outre, veuillez envisager de mettre à niveau dès que possible car cela implique des problèmes de sécurité (les secrets sont affichés dans les journaux, dans le proxy, à travers plusieurs emplacements involontaires).

Cette page vous a été utile?
0 / 5 - 0 notes