Pourquoi y a-t-il un flux «Code d'autorisation» dans OAuth2 alors que le flux «implicite» fonctionne si bien?

264

Avec le flux "implicite", le client (probablement un navigateur) obtiendra un jeton d'accès, après que le propriétaire de la ressource (c'est-à-dire l'utilisateur) ait donné l'accès.

Cependant, avec le flux "Code d'autorisation", le client (généralement un serveur Web) n'obtient un code d'autorisation qu'une fois que le propriétaire de la ressource (c'est-à-dire l'utilisateur) a donné l'accès. Avec ce code d'autorisation, le client effectue ensuite un autre appel à l'API en passant client_id et client_secret avec le code d'autorisation pour obtenir le jeton d'accès. Tout est bien décrit ici .

Les deux flux ont exactement le même résultat: un jeton d'accès. Cependant, le flux "implicite" est beaucoup plus simple.

La question: pourquoi s'embêter avec le flux "Code d'autorisation", alors que le flux "implicite" semble bien fonctionner? Pourquoi ne pas également utiliser "Implicit" pour le serveur Web?

C'est plus de travail à la fois pour le fournisseur et le client.

Aron Woost
la source
4
Consultez stackoverflow.com/questions/7522831/…
Jon Nylander
1
Merci, lisez-le déjà. Ne répond pas à la question.
Aron Woost
1
Bonne question en fait et rarement répondu :) Voir ci-dessous.
Nicolas Garnier
1
@AronWoost Je pense que vous comprenez mal l'application Web du serveur et l'application du navigateur
onmyway133
@entropy C'était ma question; pourquoi ne pas utiliser le flux du navigateur pour le serveur également.
Aron Woost

Réponses:

294

tl; dr: Tout cela pour des raisons de sécurité.

OAuth 2.0 voulait répondre à ces deux critères:

  1. Vous souhaitez autoriser les développeurs à utiliser l'URI de redirection non HTTPS car tous les développeurs n'ont pas de serveur compatible SSL et s'ils le font, il n'est pas toujours correctement configuré (non-signé, certificats SSL de confiance, horloge du serveur synchronisé ...).
  2. Vous ne voulez pas que les pirates puissent voler des jetons d'accès / d'actualisation en interceptant les demandes.

Détails ci-dessous:

Le flux implicite n'est possible que dans un environnement de navigateur pour des raisons de sécurité:

Dans le flux implicite, le jeton d'accès est transmis directement en tant que fragment de hachage (et non en tant que paramètre d'URL). Une chose importante à propos du fragment de hachage est que, une fois que vous suivez un lien contenant un fragment de hachage, seul le navigateur est au courant du fragment de hachage. Les navigateurs transmettront le fragment de hachage directement à la page Web de destination (l'URI de redirection / la page Web du client). Le fragment de hachage a les propriétés suivantes:

  • Ils ne font pas partie de la requête HTTP, ils ne peuvent donc pas être lus par les serveurs et de ce fait, ils ne peuvent pas être interceptés par des serveurs / routeurs intermédiaires (c'est important).
  • Ils n'existent que du côté du navigateur - côté client - donc la seule façon de lire le fragment de hachage est d'utiliser JavaScript qui s'exécute sur la page.

Cela permet de transmettre un Token d'accès directement au client sans risque d'être intercepté par un serveur intermédiaire. Cela a la mise en garde d'être uniquement possible côté client et nécessite que javascript soit exécuté côté client pour utiliser le jeton d'accès.

Le flux implicite présente également des problèmes de sécurité qui nécessitent une logique supplémentaire pour contourner / éviter, par exemple:

  • Un attaquant pourrait obtenir un jeton d'accès d'un utilisateur sur un autre site Web / application (disons s'il est le propriétaire de l'autre site Web / application), enregistrer le jeton sur son site Web, puis le transmettre en tant que paramètre d'URL sur votre site Web. donc usurper l'identité de l'utilisateur sur votre site Web. Pour éviter cela, vous devez vérifier l'ID client associé au jeton d'accès (par exemple pour Google, vous pouvez utiliser le point de terminaison tokeninfo) pour vous assurer que le jeton a été émis avec votre propre ID client (c'est-à-dire par votre propre application) ou vérifier la signature si vous utilisez un IDToken (mais cela nécessite le secret de votre client).
  • Si la demande d'authentification ne provient pas de votre propre propriété (appelée attaques de fixation de session), pour éviter cela, vous voudrez générer un hachage aléatoire à partir de votre site Web, l'enregistrer dans un cookie et transmettre ce même hachage dans le paramètre d'URL d'état de la demande d'authentification, lorsque l'utilisateur revient, vous vérifiez le paramètre d'état avec le cookie et il doit correspondre.

Dans le flux de code d'autorisation, il n'est pas possible de passer un jeton d'accès directement dans un paramètre d'URL car les paramètres d'URL font partie de la demande HTTP, par conséquent, tout serveur / routeur intermédiaire par lequel votre demande passerait (des centaines) pourrait être en mesure de lisez le jeton d'accès si vous n'utilisez pas de connexion cryptée (HTTPS) autorisant ce que l'on appelle les attaques d'homme au milieu

Passer le jeton d'accès directement dans un paramètre d'URL pourrait en théorie être possible, mais le serveur d'authentification devrait s'assurer que l'URI de redirection utilise HTTPS avec le cryptage TLS et un certificat SSL `` de confiance '' (généralement d'une autorité de certification qui n'est pas gratuite) pour être sûr que le serveur de destination est légitime et que la requête HTTP est entièrement cryptée. Faire en sorte que tous les développeurs achètent un certificat SSL et configurent correctement SSL sur leur domaine serait une énorme douleur et ralentirait considérablement l'adoption. C'est pourquoi un "code d'autorisation" à usage unique intermédiaire est prévu que seul le destinataire légitime pourra échanger (car vous avez besoin du secret client) et que le code sera inutile aux pirates potentiels interceptant les demandes sur des transactions non cryptées (parce qu'ils ne

Vous pouvez également affirmer que le flux implicite est moins sécurisé, il existe des vecteurs d'attaque potentiels comme l'usurpation du domaine lors de la redirection - par exemple en détournant l'adresse IP du site Web du client. C'est l'une des raisons pour lesquelles le flux implicite n'accorde que des jetons d'accès (qui sont censés avoir une utilisation limitée dans le temps) et ne rafraîchit jamais les jetons (qui sont illimités dans le temps). Pour remédier à ce problème, je vous conseille d'héberger vos pages Web sur un serveur compatible HTTPS dans la mesure du possible.

Nicolas Garnier
la source
12
@AndyDufresne Ces deux demande doivent être faites via HTTPS (obligatoire) , car ils sont des demandes au serveur OAuth qui doit prendre en charge que le protocole HTTPS. Seul le serveur client / demandeur ne doit pas prendre en charge HTTPS, donc seul le Auth Codeest potentiellement envoyé en clair via HTTP. Mais le Auth Codeest inutile sans l'ID client / secret. Fondamentalement, l'objectif du flux de code OAuth est que le fardeau d'avoir un serveur compatible SSL incombe au fournisseur OAuth (Google / Facebook, etc.) et non aux utilisateurs des API (vous, moi).
Nicolas Garnier
5
Ok, je comprends maintenant que le code d'authentification peut être transmis via HTTP simple et risque d'être reniflé. En en faisant un code à usage unique et en acceptant le secret client pour l'échanger contre un jeton d'accès, le serveur d'autorisation pourrait empêcher l'attaque de l'homme du milieu. Mais cela ne s'applique-t-il pas également au jeton d'accès? Étant donné que l'utilisateur des API peut être sur HTTP simple, le pirate ne risque-t-il pas de renifler le jeton d'accès? PS - J'apprécie vos efforts pour expliquer le concept même après un certain temps depuis que ce fil était actif. Merci !
Andy Dufresne
8
no pb :) Les demandes à l'API - c'est-à-dire lorsque le jeton d'accès est envoyé sur le câble (pour autoriser la demande) - se font également obligatoirement via HTTPS. En théorie, le client ne devrait jamais envoyer le jeton d'accès par câble en HTTP simple à tout moment.
Nicolas Garnier
5
Le jeton d'accès de cette étape fait partie de la réponse de la demande HTTPS du client au serveur de ressources. Cette réponse est toujours cryptée.
Nicolas Garnier
13
Fondamentalement, les demandes qui sont lancées du client vers le serveur de ressources sont effectuées via HTTPS (car le serveur propriétaire de la ressource doit prendre en charge HTTPS). Ce ne sont que les demandes qui sont lancées ailleurs vers le client qui peuvent être effectuées via HTTP (car le serveur client peut ne pas prendre en charge HTTPS). Par exemple, la redirection qui se produit pendant le flux d'authentification après que l'utilisateur accorde l'autorisation sur la page Gant est une redirection initiée depuis le navigateur vers le serveur client et peut être effectuée en HTTP.
Nicolas Garnier
8

Le flux implicite rend l'ensemble du flux assez facile, mais aussi moins sécurisé .
Étant donné que l'application cliente, qui exécute généralement JavaScript dans un navigateur, est moins fiable, aucun jeton d'actualisation pour un accès de longue durée n'est renvoyé.
Vous devez utiliser ce flux pour les applications qui nécessitent un accès temporaire (quelques heures) aux données de l'utilisateur.
Le retour d'un jeton d'accès aux clients JavaScript signifie également que votre application basée sur un navigateur doit faire particulièrement attention - pensez aux attaques XSS qui pourraient divulguer le jeton d'accès à d'autres systèmes.

https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow

Lakesare
la source
Je m'attendrais à ce que lorsque l'on a une vulnérabilité XSS, alors même le flux de code d'autorisation n'aide pas beaucoup. Mais je suis d'accord que depuis que la façon dont le jeton d'accès est transmis à javascript dans le flux implicite est normalisée (comme un fragment de hachage), et s'il y a une vulnérabilité XSS dans le site Web, alors construire une attaque qui lit le jeton d'accès à partir du hachage d'URL fragment est assez facile. Avec le flux de code d'autorisation, en revanche, la falsification de demande intersite peut être possible.
Marcel
En outre, il ne s'agit pas uniquement de scripts intersites. Toute bibliothèque JavaScript exécutée sur votre site Web peut essayer de voler le jeton d'accès (par exemple les bibliothèques CDN tierces ou les bibliothèques open source que votre infrastructure javascript utilise).
Marcel
2
XSS n'est plus un gros problème maintenant lorsque nous avons des en-têtes de politique de sécurité du contenu et des hachages SRI (Sub Resource Integrity).
Sergey Ponomarev
4

D'après la spécification OAuth :

4.2. Subvention implicite

Le type d'autorisation implicite est utilisé pour obtenir des jetons d'accès (il ne prend pas en charge l'émission de jetons d'actualisation) et est optimisé pour les clients publics connus pour exploiter un URI de redirection particulier. Ces clients sont généralement implémentés dans un navigateur utilisant un langage de script tel que JavaScript.

Comme il s'agit d'un flux basé sur la redirection, le client doit être capable d'interagir avec l'agent utilisateur du propriétaire de la ressource (généralement un navigateur Web) et de recevoir les demandes entrantes (via la redirection) du serveur d'autorisation.

Contrairement au type d'octroi de code d'autorisation, dans lequel le client fait des demandes d'autorisation et de jeton d'accès distinctes, le client reçoit le jeton d'accès à la suite de la demande d'autorisation.

Le type d'octroi implicite n'inclut pas l'authentification du client et dépend de la présence du propriétaire de la ressource et de l'enregistrement de l'URI de redirection. Étant donné que le jeton d'accès est codé dans l'URI de redirection, il peut être exposé au propriétaire de la ressource et à d'autres applications résidant sur le même appareil.

Donc, ce que nous pouvons considérer:

  1. Ceci est pour OAuth public, c'est-à-dire lorsque le client n'a pas besoin d'être enregistré et n'a pas ses propres secrets client. Mais les vérifications du serveur d'authentification redirigent l'URL et cela est en fait suffisant pour la sécurité.

  2. Le jeton d'accès se produit dans la barre d'adresse du navigateur afin que l'utilisateur puisse copier l'URL et l'envoyer à quelqu'un d'autre et il est également enregistré en tant qu'utilisateur, c'est-à-dire quelque chose comme la fixation de session. Mais le navigateur fait une redirection supplémentaire en remplaçant l'historique pour supprimer le fragment de hachage de l'url. Il est également possible à un pirate de voler le jeton d'accès en reniflant un trafic HTTP mais cela peut être facilement protégé par HTTPS. Certaines extensions de navigateur malveillantes peuvent avoir accès aux URL à partir de la barre d'adresse, mais c'est finalement une mauvaise situation comme un certificat HTTPS cassé. Et même le flux de code Auth ne peut pas aider ici l'éther. Donc, ce que je peux voir, c'est que passer un jeton d'accès via un fragment de hachage d'URL est absolument sûr.

  3. La séparation du jeton d'accès éphémère et du jeton de rafraîchissement est inutile lorsque vous utilisez un HTTPS et pour être honnête, pas si utile même sur HTTP brut. Mais le fait que le client via le flux implicite ne puisse pas recevoir le jeton d'actualisation est également un non-sens.

Ainsi, je pense que nous devrions introduire un nouveau flux de subvention «sûr implicite» qui fonctionne strictement sur https, permet d'actualiser le jeton (ou nous devrions nous en débarrasser) et est préférable au flux de subvention Auth Cose

stokito
la source
3

Pour nous, nos clients voulaient pouvoir s'authentifier avec notre application sur leurs téléphones une fois, et ne pas avoir à se reconnecter pendant des semaines à la fois. Avec le flux de code, vous obtenez un jeton d'actualisation avec votre jeton d'accès. Le flux implicite ne vous donne pas de jeton d'actualisation. Le jeton d'accès a une expiration relativement courte, mais les jetons d'actualisation peuvent avoir jusqu'à une expiration de 90 jours. Chaque fois que le jeton d'accès expire, le code client et serveur peut utiliser ce jeton d'actualisation pour obtenir un nouveau jeton d'accès plus un jeton d'actualisation, le tout en arrière-plan, sans aucune intervention de l'utilisateur. Un jeton d'actualisation ne peut être utilisé qu'une seule fois. Vous ne pouvez pas le faire avec Implicit Flow. Si vous utilisez Implicit Flow et que votre utilisateur n'interagit pas avec votre application pendant plus d'une heure, il devra se reconnecter à son retour. Ce n'était pas acceptable dans notre cas d'utilisation,

Cela fonctionne et est sécurisé car les jetons d'actualisation peuvent être révoqués. Si un client dit qu'il a perdu son téléphone ou son ordinateur portable ou qu'un pirate informatique s'est installé sur son bureau, nous pouvons simplement révoquer tous les jetons d'actualisation pour cet utilisateur. Pendant tout le processus, aucune information personnellement identifiable (PII) ne touche jamais notre code - à savoir le mot de passe de l'utilisateur.

Le flux de code est génial, mais cela demande plus de travail. MS n'a pas de bibliothèque angulaire pour le gérer actuellement, j'ai donc dû en écrire une. Si vous êtes intéressé, je peux vous aider.

Tim Hardy
la source
2

Ma réponse est: vous ne pouvez pas implémenter le flux implicite de manière sûre et simple avec le serveur d'application Web.

Le processus d'autorisation de l'application Web implique une interaction de l'utilisateur, donc Authentication Server doit rediriger le navigateur de l'utilisateur vers la page cible de l'application Web après l'authentification et le consentement de l'utilisateur (je ne vois pas d'autre moyen de renvoyer l'utilisateur à l'application Web après une interaction avec Serveur d'authentification).

Donc, le jeton devrait être transmis à l'application Web à l'aide de l'URL de redirection, non?

Comme @NicolasGarnier l'a expliqué dans sa réponse et ses commentaires, il n'y a aucun moyen de passer le jeton en tant que fragment d'URL - il n'atteindra pas le serveur d'application Web.

Et passer un jeton comme paramètre d'URL de l'URL de redirection serait dangereux même sous HTTPS: si la page cible (que ce soit "page d'accueil") contient des ressources (images, scripts, etc.), ces ressources seront obtenues par navigateur via la série des requêtes HTTP (S) (dont chacune a un Refereren-tête HTTP contenant l'URL exacte de la "page d'accueil", y compris les paramètres d'URL). C'est ainsi que le jeton peut fuir.

Il semble donc qu'il n'y ait aucun moyen de passer un jeton dans l'URL de redirection. C'est pourquoi vous avez besoin d'un deuxième appel (du serveur d'authentification au client (mais à quelle URL?) Ou du client au serveur d'authentification (le deuxième appel dans le flux de code d'autorisation))

Lu55
la source