Comment concevoir l'authentification des utilisateurs à partir des applications clientes?

14

J'ai développé une application qui supportera de nombreux utilisateurs. Le problème est que je ne peux pas comprendre comment authentifier le client / utilisateur.

Je crée une application comme http://quickblox.com/ où je donnerai des informations d'identification à mes utilisateurs et ils les utiliseront pour créer N applications dans lesquelles ils ne pourront pas mettre leur nom d'utilisateur et leur mot de passe pour s'authentifier.

Supposons que cela se passe comme suit. (Tout comme QuickBlox)

1. L'utilisateur crée un compte sur mon site Web.
2. L'utilisateur peut créer N clés API et sécréter des informations d'identification. (Pour plusieurs applications)
3. L'utilisateur utilisera ces informations d'identification dans ses applications (Android, iOS, Javascript, etc.) pour parler avec mes API REST.
(Les API REST ont un accès en lecture et en écriture.)

Ma préoccupation?

Les utilisateurs mettront leurs informations d'identification (clé API et clé secrète) dans les applications qu'ils créent, que se passe-t-il si quelqu'un obtient ces clés et essaie d'imiter l'utilisateur? (En décompilant l'APK ou en consultant directement le code JavaScript.

Ai-je tort quelque part?
Je suis confus pour concevoir ce mécanisme utilisateur à trois niveaux.

Alok Patel
la source
La chose que vous semblez essayer de faire n'est pas possible.
user253751
Il existe de nombreuses applications qui font la même chose. Je ne sais pas comment authentifient-ils les utilisateurs.
Alok Patel
Essayez-vous d'authentifier l' application cliente ou l' utilisateur ? De nombreuses applications authentifient les utilisateurs. Aucun d'eux n'authentifie les applications clientes de manière incassable.
user253751
Oui, par client, je veux seulement authentifier l'utilisateur.
Alok Patel
4
Oh, eh bien, dans le système d'authentification le plus typique, vous demandez simplement à l'utilisateur d'entrer son nom d'utilisateur et son mot de passe, et de les envoyer en toute sécurité au serveur qui les vérifie et (en toute sécurité) renvoie un jeton de session, puis vous envoyez le jeton de session en chaque demande future.
user253751

Réponses:

7

Je conçois des API REST depuis quelques années. Vous vous inquiétez trop. Récemment, un autre utilisateur de ce forum a posé une question, où il craignait de stocker les points de terminaison URI dans son code côté client JavaScript .

Les mêmes règles s'appliquent à vous que celles applicables au développeur JavaScript. Si vous autorisez des personnes de l'extérieur à intégrer votre API, votre API a la même visibilité qu'un site Web normal et vous devez la traiter de la même manière.

Citation de la réponse originale:

Lorsque vous créez un site Web et que vous ne voulez pas que les utilisateurs fassent quelque chose, vous n'implémentez pas cette fonctionnalité ou interdisez à certains utilisateurs de l'utiliser. Avec une API REST qui devrait avoir des points de terminaison publics, c'est à peu près la même chose, vous devez la traiter comme un site Web public.

Votre API REST doit être suffisamment robuste pour ne pas autoriser des opérations non valides, telles que l'accès aux données d'un autre utilisateur.

Vous devez concevoir vos jetons d'accès à l'application pour n'autoriser que les opérations que vous souhaitez autoriser. Vous pouvez avoir deux types de jetons d'accès:

  • jeton maître : pourrait être utilisé par le créateur de l'application et fournir plus de fonctionnalités à partir de votre API,
  • jeton d'application : le jeton qui serait réellement stocké dans les applications et n'aurait qu'un accès limité à votre API, uniquement aux opérations qui ne peuvent pas corrompre la vôtre ou les données du programmeur d'application.

Mais qu'est-ce que quelqu'un déconstruit le code source, prend les jetons de l'application, découvre quels sont les points de terminaison publics et abuse de votre service Web?

À moins que vous ne gériez directement le développement des applications consommant votre API, rien n'interdit vraiment aux gens d'abuser de votre API de la même manière directement depuis l'application.

Andy
la source
Bonne explication jusqu'à présent, j'ai une question cependant. Disons que l'une de mes API est conçue pour récupérer toutes les données associées (A + B) de mon utilisateur . Mon utilisateur utilise cette API dans son application pour obtenir uniquement le filtered data(B) de son utilisateur . Est-il maintenant possible, ou existe-t-il une solution de contournement pour empêcher un troisième utilisateur de voler toutes les données (A + B) de mon utilisateur . Est-ce que ça fait du sens?
Alok Patel
@AlokPatel Il n'y a pas d'autre solution de contournement pour simplement ne pas implémenter la fonctionnalité. Lorsque vous le faites, il y a toujours le risque que quelqu'un usurpe son hachage d'identité pour ressembler à quelqu'un d'autre. Par programme, votre problème ne peut pas être résolu. Comme je l'ai dit, si vous ne voulez pas offrir de fonctionnalités, ne les implémentez pas. Étant donné que les applications stockeront probablement le hachage de connexion en leur sein, une fois l'application déployée, votre clé API l'est également et elle n'est pas accessible au public.
Andy
Merci pour l'explication. Donc, jusqu'à présent, les API REST sont les mêmes que tous les sites Web que nous déployons, elles sont aussi ouvertes que les sites Web. Si je ne veux pas que l'utilisateur fasse quelque chose, je ne l'implémente tout simplement pas dans mes API REST. Donc, ce que je peux faire, c'est d'avoir des clés séparées pour les bibliothèques clientes (Android, iOS, JS) qui peuvent être compromises avec moins de fonctionnalités et des clés différentes qui seront utilisées côté serveur (PHP, Java, node.js) avec des fonctionnalités étendues. J'espère que cela fonctionnera!
Alok Patel
Pouvez-vous m'expliquer votre point? A moins que vous ne gériez directement le développement des applications consommant votre API
Alok Patel
@AlokPatel Ce que je voulais dire, c'est qu'en ce moment vous vous inquiétez de donner à quelqu'un l'accès à l'API, il se peut qu'il distribue l'accès et commence à abuser de l'API. Si vous n'avez aucun contrôle sur le développement des applications consommant votre API, elles peuvent faire de même, même de leur propre chef.
Andy
5

Votre problème n'est pas tant technique que commercial.

Disons que vous disposez de votre API, que vous vendez à vos clients (les développeurs d'applications) pour un montant forfaitaire de 100 £ par an, un accès illimité.

Eh bien, évidemment, je peux acheter votre service à 100 £ et le revendre à 10 personnes à 50 $ chacune. Tu ne veux pas ça! vous essayez donc de penser à une restriction qui vous permettra de vendre votre API sans qu'elle soit ouverte à l'arbitrage.

  • Si vous limitez simplement le nombre d'applications, un client peut créer une seule application qui accepte les connexions d'autres applications et les transmet.

  • Si vous limitez les utilisateurs, encore une fois, le client peut masquer les utilisateurs derrière sa propre authentification et apparaître comme un seul utilisateur.

Ce que vous devez faire, c'est transmettre le coût de chaque appel API à votre client. c'est-à-dire facturer par appel API ou définir un quota d'appels par an.

Cela pousse le même problème d'arbitrage sur vos clients. Cela les oblige à mettre en place des mesures pour empêcher leurs utilisateurs de voler leurs clés. Dans ce cas, cachez votre API derrière leur propre API authentifiée par l'utilisateur.

Ewan
la source
J'ai déjà prévu de limiter l'utilisation de mon API en fonction du nombre d'appels d'API, donc le problème lié aux affaires n'est pas mon problème pour le moment, je ne suis préoccupé que par le vol des clés.
Alok Patel
Du point de vue commercial, le problème est insoluble. Malheureusement, vous ne pouvez pas non plus le résoudre par programme.
Andy
1
Le problème commercial est résolu en facturant par appel. Si la clé est volée, votre client perd. Pas toi. Donnez simplement à votre client un moyen d'annuler les clés volées et dites-lui que c'est à lui d'avoir une API intermédiaire pour éviter les abus
Ewan
2

Les autres réponses semblent toutes suggérer que le problème du stockage d'un secret dans une application sur des appareils grand public n'est pas résoluble.

Bien sûr que ça l'est.

Deux principes (les détails de mise en œuvre suivront):

  1. Les points finaux d'authentification réels doivent être ouverts au public de manière anonyme.
  2. Le serveur doit d'une manière ou d'une autre être impliqué dans l'authentification du client et la fourniture d'une clé API.

Étant donné que, si le client fait une demande au point de terminaison d'authentification avec des informations d'identification, et que le serveur l'authentifie, le serveur peut générer un jeton temporaire dynamique (temporaire signifiant temporellement). Ce jeton doit être mémorisé dans le client et envoyé avec les demandes suivantes.

Vous aurez besoin d'un mécanisme pour «actualiser» périodiquement le jeton, c'est-à-dire en obtenir un nouveau. Créez simplement un point de terminaison REST qui permet de générer un nouveau jeton à partir d'un point existant, pour éviter d'avoir à vous authentifier à nouveau à partir des informations d'identification.

Si vous essayez d'éviter que l'utilisateur final ne s'authentifie de nouveau, cette authentification peut être une configuration initiale unique dans l'application lors de son installation.

Cette solution évite simplement la nécessité de stocker un jeton statique incorporé dans le binaire de l'application. Un jeton est généré à la volée par le serveur uniquement en réponse à une authentification réussie. Pour qu'un utilisateur malveillant inspecte votre application et essaie d'obtenir un accès API non autorisé, il devra toujours s'authentifier comme tout le monde.

Brandon
la source
Solution intéressante, bien qu'elle repose principalement sur la façon dont les clients du PO coderont leur application. Cela dit, l'approche proposée pourrait alors permettre de stocker le côté serveur de clés API et, après une authentification réussie de leurs propres utilisateurs, pourrait transmettre la clé temporaire pour l'application réelle à utiliser. de cette façon, rien n'est stocké dans l'application elle-même.
Newtopian
Cela est vrai de toutes les API. Si un consommateur d'API ne la consomme pas correctement, les choses peuvent ne pas fonctionner. Cela devrait être une partie documentée de l'API.
Brandon
Soit dit en passant, il existe des normes pour faciliter les choses, comme OAuth.
Brandon
0

Si vous avez des clés uniques par application, vous ne pouvez les utiliser que lors d'une authentification de connexion initiale, lancée par le client, après quoi vous passez à un jeton d'authentification unique par application mobile.

Votre serveur modifie (roule) le jeton de chaque application cliente de temps à autre (périodiquement, plus / moins un certain délai aléatoire flou / aléatoire, par exemple). Le jeton roulant n'est connu qu'entre le serveur et le client authentifié.

Les nouveaux jetons sont retournés piggy-back sur les réponses régulières. Chaque fois que la réponse contient un nouveau jeton, l'application réceptrice doit passer à son utilisation dans les demandes suivantes.

Chaque fois que l'échange avec un client se désynchronise (une erreur de protocole quelconque), votre serveur demandera une ré-authentification (par le biais d'une réponse d'erreur à la prochaine demande du client, ou s'appuiera sur la réponse valide à la demande du client, pour exemple).

L'authentification initiale initiée par les clients alors qu'un jeton roulant est activement utilisé doit être considérée avec suspicion - cela pourrait très bien être une tentative de mimétisme. Je ne l'autoriserais que si l'échange devient inactif pendant un intervalle plus long que prévu, ce qui pourrait, par exemple, être causé par une panne / redémarrage du client avec une nouvelle instance qui n'a pas le jeton roulant.

Il serait encore mieux de conserver le jeton du côté client de sorte qu'un client redémarré puisse continuer d'où son prédécesseur est parti - en réduisant considérablement l'ouverture pour l'imitation.

Un tel schéma rendrait l'imitation au moins assez difficile - le client imitant devrait prévoir exactement la fenêtre lorsque le client autorisé arrêterait d'envoyer des demandes suffisamment longtemps pour que le serveur décide qu'il est acceptable d'accepter une nouvelle authentification client avec la clé prescrite. De telles demandes en dehors de la fenêtre autorisée peuvent être utilisées comme détection de tentatives de mimétisme et éventuellement initier certaines contre-mesures (liste noire IP, etc.).

Dan Cornilescu
la source
0

D'après ce que je sais, ce que vous avez mentionné est la seule façon de procéder. L'application stockant la clé est certainement un risque, mais il existe différentes manières de le contourner. Vous pouvez toujours utiliser le magasin de clés pour stocker la clé, que le codage en dur, forçant ainsi une connexion unique.

En outre, vous devez envisager de lier une clé à un client.Par conséquent, si quelqu'un imite, vous devez disposer d'une couche de sécurité pour vérifier le client, la clé et les agents utilisateurs pour bloquer immédiatement la demande. Ayez un cas d'utilisation pour ré-émettre ou vous assurer que les clés ne sont pas imitées.

Arun
la source
Qu'est-ce qui fonctionne pour JavaScript? Comment faire de l'architecte pour ça?
Alok Patel
Je suppose que vous parlez de créer une application hybride. Si tel est le cas, vous devriez certainement pouvoir créer un plugin pour stocker les clés. Si vous allez héberger l'application et parler de solution Web mobile, pensez à rendre la page à l'aide d'un conteneur et vous pouvez compter sur un jeton de session suggéré plus tôt
Arun
Non ce n'est pas le cas. Je serais le troisième meilleur fournisseur d'API, mes utilisateurs utiliseront mon service d'API dans leurs applications. Cela peut être Android, iOS, JavaScript etc ...
Alok Patel
0

Si vous comptez donner à vos clients des jetons d'autorisation pour mettre leurs applications, il sera toujours théoriquement possible pour quelqu'un de procéder à une rétro-ingénierie de l'application et de les extraire. Pour éviter cela, vous auriez besoin d'un mécanisme qui ne nécessiterait pas de secret dans l'application cliente. C'est délicat. Je peux cependant vous suggérer quelques options.

Vous avez un problème une fois que vous avez donné les informations d'identification, vous n'avez aucun contrôle sur la sécurité de leur stockage. De plus, si vous demandez à l'utilisateur de vous envoyer les informations d'identification, quelqu'un peut MITM votre connexion et voler les jetons directement sans se soucier de l'ingénierie inverse de l'application.

Une façon de rendre plus difficile l'extraction de votre jeton d'autorisation est de le masquer. Cela soulève simplement la barre, mais ne le rend pas impossible, et pour ce faire, vous devrez garder le contrôle du secret. Vous pouvez implémenter une bibliothèque contenant les informations secrètes et spécifique à chaque client. Vous pouvez utiliser la bibliothèque pour communiquer avec vos serveurs et vous n'aurez peut-être même pas à dire à votre utilisateur les informations secrètes, elles pourraient simplement être intégrées dans la bibliothèque. Cela ne résout pas le problème de l'ingénierie inverse de votre bibliothèque, mais cela vous permet de contrôler le niveau d'obscurcissement. Un inconvénient est qu'une fois qu'une personne a brisé l'obscurcissement dans la bibliothèque, elle peut attaquer n'importe quelle bibliothèque, à moins que vous n'écriviez du code qui rend chaque bibliothèque significativement différente. Cela introduit son propre ensemble de problèmes.

Cela peut s'écarter légèrement de la portée de votre question, mais cela est lié à la sécurité de votre jeton, je vais donc le mentionner. Pour éviter le vol trivial du jeton sur le câble, vous ne souhaiterez probablement pas envoyer le jeton directement, mais vous pourriez signer le trafic à l'aide d'une fonction HMAC. Vous pouvez vérifier la validité du message en calculant le HMAC du message sur le serveur et en le comparant au HMAC envoyé par le client. Vous utiliseriez le jeton comme clé de la fonction HMAC afin que seule une personne connaissant le jeton puisse signer le trafic. C'est mieux pour la sécurité de votre token car vous ne l'envoyez jamais directement au serveur, il ne peut donc pas être intercepté et volé directement. Pour plus d' informations sur HMAC voir cette question: /security/20129/how-and-when-do-i-use-hmac/20301

Aucune solution de sécurité ne sera imprenable, vous devez décider combien cela vous coûtera à mettre en œuvre par rapport à la probabilité et au coût d'être compromis.

ThePragmatist
la source
Je ne peux pas créer une bibliothèque et y mettre des secrets, ceux-ci seront différents pour chacun de mes utilisateurs.
Alok Patel
Pour clarifier, je proposais que vous puissiez créer une bibliothèque personnalisée pour chacun de vos utilisateurs et masquer leurs secrets individuels à l'intérieur de la bibliothèque. Vous auriez besoin d'écrire un système pour générer automatiquement les bibliothèques à la demande pour chaque nouvel utilisateur, ce qui pourrait représenter plus de travail que vous ne le souhaitez.
ThePragmatist
0

Vous citer:

Je ne peux pas comprendre comment authentifier le client / utilisateur ... dans lequel ils ne peuvent pas mettre leur nom d'utilisateur et leur mot de passe pour s'authentifier.

Maintenant, c'est un peu une contradiction, n'est-ce pas? ;)

Comme d'autres l'ont dit, vous ne pouvez pas. Si une application utilise une clé API, on peut la décompiler comme vous le dites pour obtenir la ou les clés et l'utiliser également.

En plus d'exiger une authentification utilisateur appropriée supplémentaire, vous ne pouvez que limiter les dommages:

  • IP sur liste blanche / liste noire
  • étranglement
  • Détection "activité inhabituelle" et sa source
  • renouvellement facile des clés
dagnelies
la source