Secrets OAuth dans les applications mobiles

137

Lorsque vous utilisez le protocole OAuth, vous avez besoin d'une chaîne secrète obtenue du service auquel vous souhaitez déléguer. Si vous faites cela dans une application Web, vous pouvez simplement stocker le secret dans votre base de données ou sur le système de fichiers, mais quelle est la meilleure façon de le gérer dans une application mobile (ou une application de bureau d'ailleurs)?

Le stockage de la chaîne dans l'application n'est évidemment pas bon, car quelqu'un pourrait facilement la trouver et en abuser.

Une autre approche consisterait à le stocker sur votre serveur et à demander à l'application de le récupérer à chaque exécution, sans jamais le stocker sur le téléphone. C'est presque aussi grave, car vous devez inclure l'URL dans l'application.

La seule solution viable que je peux trouver est d'abord d'obtenir le jeton d'accès comme d'habitude (de préférence en utilisant une vue Web à l'intérieur de l'application), puis d'acheminer toutes les autres communications via notre serveur, ce qui ajouterait le secret aux données de la demande et communiquerait. avec le fournisseur. Là encore, je suis un noob de la sécurité, donc j'aimerais vraiment entendre les opinions de personnes bien informées à ce sujet. Il ne me semble pas que la plupart des applications vont à ces longueurs pour garantir la sécurité (par exemple, Facebook Connect semble supposer que vous mettez le secret dans une chaîne directement dans votre application).

Autre chose: je ne pense pas que le secret soit impliqué dans la demande initiale du jeton d'accès, donc cela pourrait être fait sans impliquer notre propre serveur. Ai-je raison?

Felixyz
la source
Désolé si je ne comprends pas l'évidence, mais quel est le problème avec le stockage des codes dans la base de données de l'application? Étant donné que ces jetons sont générés et stockés après que l'utilisateur a authentifié son compte, il devrait donc être prudent de supposer que ledit utilisateur souhaite que l'appareil mobile stocke l'accès pour avoir accès.
poke
Même après que l'utilisateur vous a autorisé à accéder à son compte (sur Twitter, par exemple), vous devez utiliser un secret que vous avez obtenu du service auquel vous essayez d'accéder. Ce secret est utilisé dans toutes les communications avec leur serveur, avec la clé d'authentification et quelques autres clés. Donc oui, vous pouvez stocker la clé d'accès, mais le secret ne doit pas être stocké, car il pourrait être utilisé avec n'importe quelle clé d'authentification pour abuser du service. Encore une fois, je serais heureux d'être corrigé par des gens qui en savent plus à ce sujet.
Felixyz
1
OAuth propose une méthode d'authentification qui sécurise les données de connexion de l'utilisateur d'origine. Pour rendre cela possible, une nouvelle combinaison de connexion unique est générée qui ne fonctionne qu'avec la combinaison de touches unique de l' application. Le grand avantage du stockage des données de connexion de l'utilisateur est que celles-ci sont totalement sûres après la première autorisation et que dans tous les cas de violation, l'utilisateur peut simplement révoquer l'accès de l'autorisation. Et bien sûr, ne pas enregistrer le secret n'aurait pas de sens car l'utilisateur devrait alors s'authentifier à nouveau (et ce n'est pas ce que l'utilisateur souhaite lorsqu'il donne l'accès à l'application).
poke
@poke La clé d'authentification obtenue lorsque l'utilisateur approuve votre application auprès du fournisseur doit être enregistrée, mais le jeton secret que vous avez reçu du fournisseur avant de publier l'application ne doit pas (dans le cas d'une application de bureau ou mobile; si c'est une application web, vous pouvez évidemment stocker la clé sur le serveur, comme indiqué dans la question).
Felixyz
4
Selon ma compréhension de oAuth - Dans le cas d'une application de bureau, il est très facile de renifler / surveiller le trafic HTTP / HTTPS avec des outils comme celui-ci ieinspector.com/httpanalyzer/index.html Par conséquent, votre jeton et votre jeton secret peuvent être trouvés très facilement. La seule protection est donc votre secret de consommation. Maintenant, si vous stockez le secret dans l'application et que quelqu'un est capable de le trouver, il devient un jeu d'enfant d'usurper l'identité d'une autre application comme votre application. Corrigez-moi si je me trompe.
Varun

Réponses:

38

Oui, c'est un problème avec la conception OAuth auquel nous sommes confrontés. Nous avons choisi de proxy tous les appels via notre propre serveur. OAuth n'a pas été entièrement éliminé en ce qui concerne les applications de bureau. Il n'y a pas de solution parfaite au problème que j'ai trouvé sans changer OAuth.

Si vous y réfléchissez et posez la question de savoir pourquoi nous avons des secrets, c'est principalement pour la fourniture et la désactivation des applications. Si notre secret est compromis, le fournisseur ne peut vraiment révoquer que l'ensemble de l'application. Puisque nous devons intégrer notre secret dans l'application de bureau, nous sommes un peu foutus.

La solution est d'avoir un secret différent pour chaque application de bureau. OAuth ne facilite pas ce concept. Une solution consiste à demander à l'utilisateur de créer lui-même un secret et de saisir la clé lui-même dans votre application de bureau (certaines applications Facebook ont ​​fait quelque chose de similaire pendant longtemps, demandant à l'utilisateur de créer Facebook pour configurer ses quiz personnalisés et merde). Ce n'est pas une expérience formidable pour l'utilisateur.

Je travaille sur une proposition de système de délégation pour OAuth. Le concept est qu'en utilisant notre propre clé secrète que nous obtenons de notre fournisseur, nous pourrions émettre notre propre secret délégué à nos propres clients de bureau (un pour chaque application de bureau essentiellement), puis pendant le processus d'authentification, nous envoyons cette clé au niveau supérieur. fournisseur qui nous rappelle et valide à nouveau avec nous. De cette façon, nous pouvons révoquer nos propres secrets que nous émettons à chaque client de bureau. (Emprunter beaucoup de la façon dont cela fonctionne de SSL). Ce système entier serait également parfait pour les services Web à valeur ajoutée qui transmettent les appels à un service Web tiers.

Le processus peut également être effectué sans rappels de vérification de délégation si le fournisseur de niveau supérieur fournit une API pour générer et révoquer de nouveaux secrets délégués. Facebook fait quelque chose de similaire en permettant aux applications Facebook de permettre aux utilisateurs de créer des sous-applications.

Il y a quelques discussions sur le problème en ligne:

http://blog.atebits.com/2009/02/fixing-oauth/ http://groups.google.com/group/twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14

La solution Twitter et Yammer est une solution de broche d'authentification: https://dev.twitter.com/oauth/pin-based https://www.yammer.com/api_oauth_security_addendum.html

Bowling de Zac
la source
C'est très intéressant, même si cela confirme ce que je craignais, qu'OAuth ne soit pas si bon pour les applications de bureau / mobiles. Bien sûr, un attaquant devrait d'abord obtenir le secret, puis aussi renifler les informations d'identification de quelqu'un, il faudrait donc une certaine détermination. La solution de broche est correcte pour le bureau mais trop lourde pour l'imo mobile.
Felixyz
Comment votre système proposé aiderait-il les services Web à valeur ajoutée, puisque ce problème ne s'applique pas à eux? De plus, je ne vois pas comment cela fonctionnerait avec le fournisseur générant de nouveaux secrets, car vous auriez besoin d'un "secret principal" pour même demander ces nouveaux secrets, vous auriez donc au moins besoin d'un appel à votre propre serveur (qui contient le secret principal). Mais c'est bien sûr mieux que d'acheminer tout le trafic via votre propre serveur. Clarification la bienvenue! Et veuillez mettre à jour ici au fur et à mesure que votre proposition progresse!
Felixyz
5
Juste curieux: comment déterminez-vous que la chose qui appelle votre serveur proxy est légitime?
davidtbernal
1
En réponse à notJim: le principal risque en permettant à votre secret de consommateur de sortir est que des applications malveillantes (ou stupides) puissent être développées en l'utilisant, ternissant votre réputation et augmentant le risque de voir votre application légitime fermée pour abus / mauvaise utilisation d'API. En renvoyant par mandataire tous les appels qui nécessitent votre secret via une application Web que vous contrôlez, vous êtes de retour dans une position où vous pouvez surveiller les modèles d'abus et révoquer l'accès au niveau de l'utilisateur ou du jeton d'accès avant que l'API que vous consommez ne décide de fermer tout votre service.
quasistoic
Je suis d'accord avec quasistoic ici, vous devrez utiliser un navigateur compatible SSL pour traiter l'appel oauth. C'est une bonne chose pour plusieurs raisons, y compris la gestion facile des mises à jour de sécurité à l'avenir, et rien dans l'application réelle n'aura besoin d'être mis à jour au fil du temps. Zac souligne que Twitter propose une solution de code PIN, que j'ai également imaginée, car vous ne pouvez pas faire confiance à l'application pour obtenir le code en toute sécurité. Je suggère d'utiliser un «Nonce» avec un cryptage moderne avec le code PIN et le secret pour proxy les demandes via le serveur Web.
Mark du
18

Avec OAUth 2.0, vous pouvez stocker le secret sur le serveur. Utilisez le serveur pour acquérir un jeton d'accès que vous déplacez ensuite vers l'application et vous pouvez passer des appels de l'application directement à la ressource.

Avec OAuth 1.0 (Twitter), le secret est requis pour effectuer des appels API. Les appels par procuration via le serveur sont le seul moyen de garantir que le secret n'est pas compromis.

Les deux nécessitent un mécanisme que votre composant serveur sait que c'est votre client qui l'appelle. Cela a tendance à être fait lors de l'installation et à l'aide d'un mécanisme spécifique à la plate-forme pour obtenir un identifiant d'application quelconque lors de l'appel à votre serveur.

(Je suis l'éditeur de la spécification OAuth 2.0)

Dick Hardt
la source
2
Pouvez-vous élaborer sur le "mécanisme spécifique à la plate-forme pour obtenir un identifiant d'application quelconque"? Comment le composant serveur vérifie-t-il l'identité du client? Je pense que cela peut être fait avec l'approvisionnement client. Par exemple, déployez un nouveau certificat SSL unique sur chaque client. C'est ce que tu veux dire? Si c'est plus complexe que cela, vous pouvez peut-être vous référer à un article plus détaillé?
Cheeso
2
Je me souviens que certaines personnes chargées de la sécurité parlaient de la façon dont cela pouvait être fait. Il y a un appel au système d'exploitation qui renvoie un jeton signé que vous pouvez ensuite envoyer à votre serveur et vérifier. Désolé, je n'ai pas les détails. C'est une erreur qui pourrait utiliser de bons exemples.
Dick Hardt
2
@DickHardt mais dans ce scénario comment vous assurez-vous que l'application mobile est bien votre application et non une application frauduleuse?
Rafael Membrives le
11

Une solution pourrait être de coder en dur le secret OAuth dans le code, mais pas sous forme de chaîne simple. Cachez-le d'une manière ou d'une autre - divisez-le en segments, décalez les caractères d'un décalage, faites-le pivoter - faites tout ou partie de ces choses. Un pirate peut analyser votre code d'octet et trouver des chaînes, mais le code d'obfuscation peut être difficile à comprendre.

Ce n'est pas une solution infaillible, mais une solution bon marché.

En fonction de la valeur de l'exploit, certains crackers de génie peuvent aller plus loin pour trouver votre code secret. Vous devez peser les facteurs - coût de la solution côté serveur mentionnée précédemment, incitation pour les pirates à consacrer plus d'efforts à la recherche de votre code secret et complexité de l'obfuscation que vous pouvez mettre en œuvre.

Jayesh
la source
1
Oui, je pense que c'est raisonnable. Il faudrait beaucoup de détermination pour que quelqu'un extrait d'abord le secret du consommateur, puis arrache les informations d'identification des gens pour faire quelque chose de méchant. Pour les applications de haut niveau, je ne suis pas sûr que ce serait suffisant, mais pour une application moyenne, je pense que vous avez raison de dire que vous devez équilibrer le temps de mise en œuvre par rapport à une menace de sécurité assez mineure.
Felixyz
7
Tout ce qu'il faut, c'est qu'un seul utilisateur fasse l'effort, puis publie ou partage votre secret. Une fois votre secret révélé, le risque que votre service soit complètement fermé pour abus monte en flèche, et il est complètement hors de votre contrôle.
quasistoic
8
L'obfuscation n'est pas du tout une sécurité. C'est pire que pas de sécurité du tout, car cela donne au développeur un faux sentiment de sécurité. en.wikipedia.org/wiki/Security_through_obscurity
Paul Legato
8
"L'obscurcissement n'est pas du tout une sécurité. C'est pire que pas de sécurité du tout, car cela donne au développeur un faux sentiment de sécurité." Absurdité. Personne ne dit que l'obscurcissement assure une bonne sécurité. Mais si je vais distribuer un secret OAuth avec mon apk, il vaut sûrement mieux masquer que non. L'obscurcissement est ce que Google recommande également lors du stockage des clés / secrets dans l'application. Si rien d'autre, ces mesures tiennent les pirates informatiques occasionnels à distance, ce qui est mieux que rien. Des déclarations générales comme la vôtre assimile une sécurité imparfaite à aucune sécurité. Ce n'est tout simplement pas vrai. Imparfait est tout simplement imparfait.
hungryghost
1
L'obscurcissement n'aide PAS, car peu importe la quantité de décalage ou d'encodage que vous faites, vous construisez toujours la clé ensemble et vous l'utilisez pour créer votre demande d'API. Il est assez simple d'accrocher dynamiquement les API aux bons endroits pour vider la demande que vous envoyez avant même le cryptage HTTPS. Alors s'il vous plaît, n'intégrez pas de clés secrètes dans votre application à moins qu'il n'y ait vraiment aucune alternative possible.
C0deH4cker
6

Ne stockez pas le secret dans l'application.

Vous devez avoir un serveur accessible par l'application via https (évidemment) et vous y stockez le secret.

Lorsque quelqu'un souhaite se connecter via votre application mobile / de bureau, votre application transmettra simplement la demande au serveur qui ajoutera alors le secret et l'envoyera au fournisseur de services. Votre serveur peut alors indiquer à votre application si elle a réussi ou non.

Ensuite, si vous avez besoin d'obtenir des informations sensibles du service (facebook, google, twitter, etc.), l'application demande à votre serveur et votre serveur ne les transmettra à l'application que si elle est correctement connectée.

Il n'y a pas vraiment d'autre option que de le stocker sur un serveur. Rien du côté client n'est sécurisé.

Remarque

Cela dit, cela ne vous protégera que contre les clients malveillants mais pas contre les clients malveillants et non contre les clients malveillants (phising) ...

OAuth est un bien meilleur protocole dans le navigateur que sur le bureau / mobile.

Gudradain
la source
1
cela ne facilite-t-il pas la vie du hacker?! car maintenant, pour accéder aux ressources du serveur, nous avons techniquement besoin de l'identifiant du client, puisque le serveur ajoutera de toute façon le secret à la requête. est-ce que je manque quelque chose?
Hudi Ilfeld
@HudiIlfeld Oui, il vous manque quelque chose: le client doit se connecter au serveur. Tant qu'il n'est pas connecté, le serveur ne retournera rien. Une façon de gérer cela est après avoir envoyé les informations d'identification pour la première fois, le serveur renvoie un jeton d'accès au client, puis le client envoie ce jeton d'accès avec chaque demande future. Il existe de nombreuses options ici.
Gudradain
4

Il existe une nouvelle extension du type d'autorisation de code d'autorisation appelée clé de preuve pour l'échange de code (PKCE) . Avec lui, vous n'avez pas besoin d'un secret client.

PKCE (RFC 7636) est une technique pour sécuriser les clients publics qui n'utilisent pas de secret client.

Il est principalement utilisé par les applications natives et mobiles, mais la technique peut également être appliquée à n'importe quel client public. Il nécessite une prise en charge supplémentaire de la part du serveur d'autorisation, il n'est donc pris en charge que sur certains fournisseurs.

sur https://oauth.net/2/pkce/

Pour plus d'informations, vous pouvez lire l'intégralité RFC 7636 ou cette courte introduction .

Johannes Filter
la source
2

Voici quelque chose à penser. Google propose deux méthodes d'OAuth ... pour les applications Web, où vous enregistrez le domaine et générez une clé unique, et pour les applications installées où vous utilisez la clé «anonyme».

Peut-être ai-je passé sous silence quelque chose dans la lecture, mais il semble que partager la clé unique de votre application Web avec une application installée est probablement plus sécurisé que d'utiliser «anonyme» dans la méthode officielle des applications installées.

LetMyPeopleCode
la source
2

Avec OAuth 2.0, vous pouvez simplement utiliser le flux côté client pour obtenir un jeton d'accès et utiliser ensuite ce jeton d'accès pour authentifier toutes les demandes ultérieures. Alors vous n'avez pas du tout besoin d'un secret.

Une belle description de la façon de mettre en œuvre cela peut être trouvée ici: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps

Joël Richard
la source
À condition que le service prenne en charge «le flux côté client». Beaucoup ne le font pas, exigeant à la place l'ID client et le secret client afin d'obtenir ce jeton d'accès.
Damian Yerrick
0

Je n'ai pas une tonne d'expérience avec OAuth - mais toutes les demandes ne nécessitent-elles pas seulement le jeton d'accès de l'utilisateur, mais également une clé et un secret de consommateur d'application? Ainsi, même si quelqu'un vole un appareil mobile et essaie d'en extraire des données, il aura également besoin d'une clé d'application et d'un secret pour pouvoir faire quoi que ce soit.

J'ai toujours pensé que l'intention derrière OAuth était que chaque Tom, Dick et Harry qui avaient un mashup n'ait pas à stocker vos informations d'identification Twitter en clair. Je pense que cela résout assez bien ce problème malgré ses limites. En outre, il n'a pas vraiment été conçu avec l'iPhone à l'esprit.

bpapa
la source
Vous avez raison, OAuth a été principalement conçu avec des applications Web à l'esprit et je suis sûr que cela fonctionne bien pour cela. Oui, vous avez besoin du jeton consommateur et du secret pour signer chaque demande, et le problème est de savoir où stocker le secret. Si quelqu'un vole la clé d'accès, ce n'est pas un problème car elle peut être révoquée, mais si quelqu'un obtient la clé du consommateur, chaque copie de votre application a été compromise.
Felixyz
OAuth 1 exigeait la signature de chaque demande. OAuth 2 nécessite uniquement le jeton d'accès. Les deux nécessitent la clé et le secret lors de l'acquisition d'un jeton.
Dick Hardt
0

Je suis d'accord avec Felixyz. OAuth, bien que meilleur que l'authentification de base, a encore un long chemin à parcourir pour être une bonne solution pour les applications mobiles. J'ai utilisé OAuth pour authentifier une application de téléphonie mobile auprès d'une application Google App Engine. Le fait que vous ne puissiez pas gérer de manière fiable le secret du consommateur sur l'appareil mobile signifie que la valeur par défaut est d'utiliser l'accès «anonyme».

L'étape d'autorisation du navigateur de la mise en œuvre OAuth de Google App Engine vous amène à une page contenant du texte tel que: "Le site <some-site> demande l'accès à votre compte Google pour le ou les produits répertoriés ci-dessous"

YourApp (yourapp.appspot.com) - non affilié à Google

etc

Il prend <some-site> du nom de domaine / hôte utilisé dans l'URL de rappel que vous fournissez qui peut être n'importe quoi sur Android si vous utilisez un schéma personnalisé pour intercepter le rappel. Donc, si vous utilisez un accès `` anonyme '' ou si votre secret client est compromis, n'importe qui pourrait écrire un consommateur qui trompe l'utilisateur en lui donnant accès à votre application gae.

La page d'autorisation Google OAuth contient également de nombreux avertissements qui ont 3 niveaux de gravité selon que vous utilisez des clés `` anonymes '', secrètes du consommateur ou publiques.

Des trucs assez effrayants pour l'utilisateur moyen qui n'est pas techniquement averti. Je ne m'attends pas à avoir un pourcentage de réussite d'inscription élevé avec ce genre de choses.

Cet article de blog explique comment les secrets de consommation ne fonctionnent pas vraiment avec les applications installées. http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/

Martin Bayly
la source
0

J'essaie également de trouver une solution pour l'authentification OAuth mobile et le stockage des secrets dans le paquet d'applications en général.

Et une idée folle vient de me frapper: l'idée la plus simple est de stocker le secret à l'intérieur du binaire, mais en quelque sorte obscurci, ou, en d'autres termes, vous stockez un secret crypté. Donc, cela signifie que vous devez stocker une clé pour déchiffrer votre secret, ce qui semble nous avoir bouclé la boucle. Cependant, pourquoi ne pas simplement utiliser une clé qui est déjà dans l'OS, c'est-à-dire qu'elle est définie par l'OS et non par votre application.

Donc, pour clarifier mon idée, c'est que vous choisissez une chaîne définie par le système d'exploitation, peu importe laquelle. Ensuite, cryptez votre secret en utilisant cette chaîne comme clé et stockez-la dans votre application. Ensuite, pendant l'exécution, décryptez la variable à l'aide de la clé, qui n'est qu'une constante du système d'exploitation. Tout hacker regardant dans votre binaire verra une chaîne cryptée, mais pas de clé.

Ça marchera?

Daniel Thorpe
la source
3
Bonne pensée, mais non. Le pirate verrait simplement le binaire pointant vers l'adresse de la constante du système d'exploitation.
GrayB
0

Facebook n'implémente pas (encore) OAuth à proprement parler, mais ils ont mis en place un moyen pour vous de ne pas intégrer votre secret dans votre application iPhone: https://web.archive.org/web/20091223092924/http://wiki. développeurs.facebook.com/index.php/Session_Proxy

Quant à OAuth, ouais, plus j'y pense, on est un peu bourrés. Peut - être que cela résoudra le problème.

Oliland
la source
1
wiki.developers.facebook.com est mort.
Hugo
0

Aucune de ces solutions n'empêche un pirate informatique déterminé de renifler les paquets envoyés depuis son appareil mobile (ou son émulateur) pour afficher le secret client dans les en-têtes http.

Une solution pourrait être d'avoir un secret dynamique qui est composé d'un horodatage chiffré avec une clé et un algorithme de chiffrement bidirectionnels privés. Le service déchiffre ensuite le secret et détermine si l'horodatage est de +/- 5 minutes.

De cette manière, même si le secret est compromis, le hacker ne pourra l'utiliser que pendant 5 minutes maximum.

Maximvs
la source
-2

Comme d'autres l'ont mentionné, il ne devrait y avoir aucun problème réel avec le stockage du secret localement sur l'appareil.

En plus de cela, vous pouvez toujours compter sur le modèle de sécurité basé sur UNIX d'Android: seule votre application peut accéder à ce que vous écrivez dans le système de fichiers. Écrivez simplement les informations dans l'objet SharedPreferences par défaut de votre application.

Pour obtenir le secret, il faudrait obtenir un accès root au téléphone Android.

Christophe Orr
la source
3
Comme qui l'a mentionné? Si vous voulez dire le commentaire de poke, voyez ma réponse que secret! = Clé d'authentification. Ce dernier peut être stocké en toute sécurité, le premier ne le peut pas. Je ne sais pas pour Android, mais obtenir un accès root à un iPhone n'est pas du tout difficile. Notez que le secret est le même sur toutes les instances de l'application, de sorte qu'un attaquant n'aurait qu'à accéder à un binaire. Et même s'ils ne pouvaient pas accéder à la racine de l'appareil, ils pourraient mettre la main sur le binaire d'un autre et en extraire le jeton secret.
Felixyz
1
juste pour ajouter, il est également très facile de rooter les téléphones Android
kgutteridge