Architektur der Benutzerauthentifizierung aus Clientanwendungen heraus


14

Ich habe eine Anwendung entwickelt, die viele Benutzer unterstützt. Die Sache ist, ich kann nicht herausfinden, wie man den Klienten / den Benutzer authentifiziert.

Ich erstelle eine App wie http://quickblox.com/, in der ich meinen Benutzern Anmeldeinformationen gebe und sie verwenden diese, um N Anwendungen zu erstellen, in denen sie ihren Benutzernamen und ihr Kennwort nicht eingeben können, um sich zu authentifizieren.

Nehmen wir an, es geht wie folgt. (Genau wie QuickBlox)

1. Der Benutzer erstellt ein Konto auf meiner Website.
2. Der Benutzer kann N API-Schlüssel erstellen und Anmeldeinformationen absichern. (Für mehrere Apps)
3. Der Benutzer verwendet diese Anmeldeinformationen in seinen Anwendungen (Android, iOS, Javascript usw.), um mit meinen REST-APIs zu kommunizieren.
(REST-APIs haben Lese- und Schreibzugriff.)

Mein Konzern?

Benutzer geben ihre Anmeldeinformationen (API-Schlüssel und geheimer Schlüssel) in Anwendungen ein, die sie erstellen. Was passiert, wenn jemand diese Schlüssel erhält und versucht, den Benutzer zu imitieren? (Durch Dekompilieren von APK oder direktes Betrachten von JavaScript-Code.

Irre ich mich irgendwo?
Ich bin verwirrt, diesen dreistufigen Benutzermechanismus zu entwickeln.


Das, was Sie versuchen, ist nicht möglich.
user253751

Es gibt viele Anwendungen, die dasselbe tun. Ich bin nicht sicher, wie sie die Benutzer authentifizieren.
Alok Patel

Versuchen Sie, die Clientanwendung oder den Benutzer zu authentifizieren ? Viele Apps authentifizieren Benutzer. Keiner von ihnen authentifiziert Clientanwendungen auf unzerbrechliche Weise.
user253751

Ja, vom Kunden, ich meine, ich möchte nur den Benutzer authentifizieren.
Alok Patel

4
Nun, in einem typischen Authentifizierungssystem muss der Benutzer lediglich seinen Benutzernamen und sein Kennwort eingeben und diese sicher an den Server senden, der sie überprüft und (sicher) ein Sitzungstoken zurückgibt. Anschließend senden Sie die Sitzungstoken ein jede zukünftige Anfrage.
user253751

Antworten:


7

Ich habe in den letzten Jahren REST-APIs entwickelt. Du machst dir zu viele Sorgen. Kürzlich hat ein anderer Benutzer in diesem Forum eine Frage gestellt, wo er sich Sorgen über das Speichern von URI-Endpunkten in seinem clientseitigen JavaScript-Code gemacht hat .

Für Sie gelten die gleichen Regeln wie für den JavaScript-Entwickler. Wenn Sie zulassen, dass Dritte Ihre API integrieren, hat Ihre API dieselbe Sichtbarkeit wie eine normale Website und Sie sollten sie auf dieselbe Weise behandeln.

Zitat aus der ursprünglichen Antwort:

Wenn Sie eine Website erstellen und Sie möchten, dass Benutzer nichts tun, implementieren Sie diese Funktionalität nicht und verbieten Sie bestimmten Benutzern, sie zu verwenden. Mit einer REST-API, die öffentliche Endpunkte haben sollte, ist es fast dasselbe. Sie müssen sie wie eine öffentliche Website behandeln.

Ihre REST-API sollte robust genug sein, um ungültige Vorgänge wie den Zugriff auf Daten eines anderen Benutzers zu verhindern.

Sie sollten Ihre Anwendungszugriffstoken so gestalten, dass nur Vorgänge zugelassen werden, die Sie zulassen möchten. Sie können zwei Arten von Zugriffstoken haben:

  • Master-Token : Kann vom Anwendungsersteller verwendet werden und bietet mehr Funktionen über Ihre API.
  • Anwendungstoken : Das Token, das tatsächlich in den Anwendungen gespeichert wird und nur eingeschränkten Zugriff auf Ihre API hat, nur auf Vorgänge, die Ihre oder die Daten des Anwendungsprogrammierers nicht beschädigen können.

Aber was dekonstruiert jemand den Quellcode, nimmt die Token aus der Anwendung heraus, findet heraus, was die öffentlichen Endpunkte sind und missbraucht Ihren Webdienst?

Wenn Sie die Entwicklung der Anwendungen, die Ihre API verwenden, nicht direkt verwalten, ist es nicht wirklich verboten, dass Benutzer Ihre API auf dieselbe Weise direkt aus der App heraus missbrauchen.


Bisher eine gute Erklärung, aber ich habe eine Frage. Angenommen, eine meiner APIs wurde erstellt, um alle zugehörigen Daten (A + B) meines Benutzers abzurufen . Mein Benutzer verwendet diese API in seiner App, um nur das filtered data(B) seines Benutzers abzurufen. Jetzt ist es möglich, oder gibt es eine Abhilfe zu verhindern dritte Benutzer alle Daten (A + B) zu stehlen meinen Benutzers . Macht das Sinn?
Alok Patel

@AlokPatel Es gibt keine andere Problemumgehung, als die Funktionalität einfach nicht zu implementieren. Wenn Sie dies tun, besteht immer das Risiko, dass jemand seine Identitäts-Hashes fälscht und wie jemand anderes aussieht. Programmatisch kann Ihr Problem nicht gelöst werden. Wie ich bereits sagte, sollten Sie einige Funktionen nicht implementieren, wenn Sie diese nicht anbieten möchten. Da die Apps wahrscheinlich den Login-Hash in ihnen speichern, ist Ihr API-Schlüssel nach der Bereitstellung der App ebenfalls vorhanden und nicht öffentlich verfügbar.
Andy

Danke für die Erklärung. Bisher habe ich festgestellt, dass REST-APIs mit allen von uns bereitgestellten Websites identisch sind. Sie sind so offen wie Websites. Wenn ich nicht möchte, dass Benutzer etwas tun, implementiere ich es einfach nicht in meinen REST-APIs. Ich kann also separate Schlüssel für Client-Bibliotheken (Android, iOS, JS) haben, die mit weniger Funktionalität kompromittiert werden können, und andere Schlüssel, die serverseitig (PHP, Java, node.js) mit erweiterter Funktionalität verwendet werden. Hoffe das klappt!
Alok Patel

Können Sie mir diesen Punkt erklären? Es sei denn, Sie verwalten direkt die Entwicklung der Anwendungen, die Ihre API nutzen
Alok Patel

@AlokPatel Was ich damit gemeint habe, ist, dass Sie sich gerade Sorgen machen, dass Sie jemandem Zugriff auf die API gewähren, er den Zugriff möglicherweise verteilt und damit beginnt, die API zu missbrauchen. Wenn Sie keine Kontrolle über die Entwicklung der Anwendungen haben, die Ihre API verbrauchen, tun sie dies möglicherweise auch für sich.
Andy

5

Ihr Problem ist weniger ein technisches als ein geschäftliches.

Nehmen wir an, Sie haben Ihre API, die Sie Ihren Kunden (den App-Entwicklern) zum Pauschalpreis von 100 GBP pro Jahr verkaufen. Unbegrenzter Zugriff.

Dann kann ich natürlich Ihren Service für 100 GBP kaufen und ihn für jeweils 50 USD an 10 Personen verkaufen. Das willst du nicht! Sie versuchen also, sich eine Einschränkung auszudenken, mit der Sie Ihre API verkaufen können, ohne dass Arbitrage möglich ist.

  • Wenn Sie nur die Anzahl der Apps beschränken, kann ein Kunde eine einzelne App erstellen, die Verbindungen von anderen Apps akzeptiert und weiterleitet.

  • Wenn Sie die Benutzer einschränken, kann der Kunde Benutzer hinter seiner eigenen Authentifizierung verstecken und als einzelner Benutzer erscheinen.

Sie müssen lediglich die Kosten für jeden API-Aufruf an Ihren Kunden weitergeben. dh Gebühr pro API-Aufruf oder Festlegen einer Quote für Aufrufe pro Jahr.

Dies bringt das gleiche Problem der Arbitrage auf Ihre Kunden. Es zwingt sie, Maßnahmen zu ergreifen, um zu verhindern, dass ihre Benutzer ihre Schlüssel stehlen. In diesem Fall verstecken Sie Ihre API hinter ihrer eigenen, vom Benutzer authentifizierten API.


Ich habe bereits geplant, die Verwendung meiner API basierend auf der Anzahl der API-Aufrufe einzuschränken, sodass geschäftliche Probleme im Moment nicht mein Problem sind. Ich mache mir nur Sorgen, dass Schlüssel gestohlen werden.
Alok Patel

Aus geschäftlicher Sicht ist das Problem unlösbar. Leider können Sie es auch nicht programmgesteuert lösen.
Andy

1
Das Geschäftsproblem wird durch Aufladen pro Anruf gelöst. Wenn der Schlüssel gestohlen wird, verliert Ihr Kunde. Nicht du. Geben Sie Ihrem Kunden einfach eine Möglichkeit, gestohlene Schlüssel zu stornieren, und sagen Sie, dass er eine Zwischen-API haben muss, um Missbrauch zu verhindern
Ewan,

2

Die anderen Antworten scheinen darauf hinzudeuten, dass das Problem der Speicherung eines Geheimnisses in einer App auf Endgeräten nicht lösbar ist.

Sicher ist es das.

Zwei Prinzipien (die Implementierungsdetails werden folgen):

  1. Die tatsächlichen Authentifizierungsendpunkte müssen anonym für die Öffentlichkeit zugänglich sein.
  2. Der Server muss irgendwie an der Authentifizierung des Clients und der Bereitstellung eines API-Schlüssels beteiligt sein.

Wenn der Client eine Anforderung mit Anmeldeinformationen an den Authentifizierungsendpunkt sendet und dieser vom Server authentifiziert wird, kann der Server ein dynamisches temporäres Token (temporär, dh zeitbasiert) generieren . Dieses Token sollte im Client gespeichert und mit nachfolgenden Anforderungen gesendet werden.

Sie benötigen einen Mechanismus, um das Token regelmäßig zu "aktualisieren", dh ein neues zu erhalten. Erstellen Sie einfach einen REST-Endpunkt, mit dem Sie aus einem vorhandenen Token ein neues Token generieren können, damit Sie sich nicht erneut anhand der Anmeldeinformationen authentifizieren müssen.

Wenn Sie verhindern möchten, dass sich der Endbenutzer erneut authentifiziert, kann diese Authentifizierung bei der Installation eine einmalige Einrichtung in der App sein.

Diese Lösung vermeidet einfach die Notwendigkeit, ein statisches Token zu speichern, das in der Anwendungsbinärdatei eingebettet ist. Ein Token wird vom Server im laufenden Betrieb nur als Antwort auf eine erfolgreiche Authentifizierung generiert. Damit ein böswilliger Benutzer Ihre Anwendung untersuchen und versuchen kann, nicht autorisierten API-Zugriff zu erhalten, muss er sich wie jeder andere auch authentifizieren.


Interessante Lösung, obwohl sie hauptsächlich davon abhängt, wie die Kunden des OP ihre App codieren. Das heißt, der vorgeschlagene Ansatz könnte es ermöglichen, den API-Schlüssel serverseitig zu speichern und nach erfolgreicher Authentifizierung der eigenen Benutzer den temporären Schlüssel zur Verwendung durch die eigentliche App weiterzuleiten. Auf diese Weise wird nichts in der App selbst gespeichert.
Newtopian

Das gilt für alle APIs. Wenn ein API-Konsument es nicht richtig konsumiert, funktionieren die Dinge möglicherweise nicht. Dies müsste ein dokumentierter Teil der API sein.
Brandon

Übrigens gibt es Standards wie OAuth, die dies einfacher machen.
Brandon

0

Wenn Sie eindeutige app-bezogene Schlüssel haben, können Sie diese nur während einer vom Client initiierten anfänglichen Verbindungsauthentifizierung verwenden. Anschließend wechseln Sie zu einem fortlaufenden, app-bezogenen eindeutigen Authentifizierungstoken.

Ihr Server ändert (rollt) das Token für jede Client-App von Zeit zu Zeit (z. B. in regelmäßigen Abständen plus / minus einer zufälligen Fuzzy- / Zufallsverzögerung). Das Rolling Token ist nur zwischen dem Server und dem authentifizierten Client bekannt.

Die neuen Token werden bei den regulären Antworten huckepack zurückgegeben. Immer wenn die Antwort ein neues Token enthält, muss die empfangende App darauf umstellen, es in nachfolgenden Anforderungen zu verwenden.

Wenn der Austausch mit einem Client nicht mehr synchron ist (irgendein Protokollfehler), fordert Ihr Server eine erneute Authentifizierung an (durch eine Fehlerantwort auf die nächste Clientanforderung oder auf die gültige Antwort auf die Clientanforderung gepackt, z Beispiel).

Die anfängliche Authentifizierung, die von Clients initiiert wird, während ein rollendes Token aktiv verwendet wird, sollte mit Argwohn betrachtet werden - es könnte sich durchaus um einen Nachahmungsversuch handeln. Ich würde es nur zulassen, wenn der Austausch für ein länger als erwartetes Intervall inaktiv ist, was zum Beispiel durch einen Clientausfall / -neustart mit einer neuen Instanz ohne Rolling Token verursacht werden könnte.

Es ist sogar noch besser, das Token auf der Clientseite beizubehalten, sodass ein neu gestarteter Client an der Stelle weitermachen kann, an der sein Vorgänger noch übrig ist, was die Öffnung für die Nachahmung erheblich einschränkt.

Ein solches Schema würde die Nachahmung zumindest ziemlich schwierig machen - der nachahmende Client müsste genau das Fenster vorhersagen, in dem der autorisierte Client keine Anfragen mehr sendet, damit der Server entscheiden kann, ob es in Ordnung ist, eine neue Clientauthentifizierung mit dem vorgeschriebenen Schlüssel zu akzeptieren. Solche Anfragen außerhalb des erlaubten Fensters können als Erkennung von Nachahmungsversuchen verwendet werden und möglicherweise Gegenmaßnahmen einleiten (IP-Blacklisting usw.).


0

Soweit ich weiß, ist das, was Sie erwähnt haben, der einzige Weg, dies zu tun. Die Anwendung, die den Schlüssel speichert, ist definitiv ein Risiko, aber es gibt verschiedene Möglichkeiten, ihn zu umgehen. Sie können den Schlüsselspeicher immer zum Speichern des Schlüssels verwenden, anstatt ihn fest zu codieren, wodurch eine einmalige Anmeldung erzwungen wird.

Sie sollten auch in Betracht ziehen, einen Schlüssel an einen Client zu binden. Wenn jemand dies nachahmt, sollten Sie über eine Sicherheitsschicht verfügen, die den Client, den Schlüssel und die Benutzeragenten überprüft, um die Anforderung sofort zu blockieren. Verwenden Sie einen Anwendungsfall, um sicherzustellen, dass die Schlüssel nicht nachgeahmt werden.


Was ist die Problemumgehung für JavaScript? Wie soll man dafür architektieren?
Alok Patel

Ich gehe davon aus, dass Sie über das Erstellen einer Hybridanwendung sprechen. Wenn dies der Fall ist, sollten Sie definitiv in der Lage sein, ein Plugin zum Speichern der Schlüssel zu erstellen. Wenn Sie die Anwendung hosten und über eine mobile Weblösung sprechen möchten, sollten Sie überlegen, ob Sie die Seite mithilfe eines Containers rendern möchten. Sie können sich dann auf ein zuvor vorgeschlagenes Sitzungstoken verlassen
Arun,

Nein, das ist nicht der Fall. Ich wäre der dritte Top-API-Anbieter. Meine Benutzer werden meinen API-Service in ihren Anwendungen verwenden. Es kann Android, iOS, JavaScript usw. sein ...
Alok Patel

0

Wenn Sie darauf angewiesen sind, Ihren Kunden Autorisierungstoken zum Einfügen ihrer Apps zu erteilen, kann theoretisch immer jemand die App zurückentwickeln und extrahieren. Um dies zu verhindern, benötigen Sie einen Mechanismus, der kein Geheimnis in der Client-App erfordert. Das ist knifflig. Ich kann Ihnen jedoch einige Optionen vorschlagen, über die Sie nachdenken sollten.

Sie haben ein Problem, nachdem Sie die Anmeldeinformationen ausgegeben haben. Sie haben keine Kontrolle darüber, wie sicher sie gespeichert werden. Wenn der Benutzer die Anmeldeinformationen an Sie senden muss, kann jemand Ihre Verbindung MITMEN und die Token direkt stehlen, ohne sich um das Reverse Engineering der App kümmern zu müssen.

Eine Möglichkeit, das Extrahieren Ihres Autorisierungstokens zu erschweren, besteht darin, es zu verschleiern. Dies legt die Messlatte nur höher, macht es aber nicht unmöglich, und um dies zu tun, müsste man die Kontrolle über das Geheimnis behalten. Sie können eine Bibliothek implementieren, die die geheimen Informationen enthält und für jeden Kunden spezifisch ist. Sie können die Bibliothek verwenden, um mit Ihren Servern zu kommunizieren, und müssen Ihrem Benutzer möglicherweise nicht einmal die geheimen Informationen mitteilen, sondern können sie einfach in die Bibliothek einbetten. Dies löst nicht das Problem, dass jemand Ihre Bibliothek zurückentwickelt, sondern gibt Ihnen die Kontrolle über den Grad der Verschleierung. Ein Nachteil ist, dass eine Person, sobald sie die Verschleierung in der Bibliothek aufgebrochen hat, jede Ihrer Bibliotheken angreifen kann, es sei denn, Sie schreiben Code, der jede Bibliothek deutlich anders macht. Das bringt seine eigenen Probleme mit sich.

Dies kann leicht vom Umfang Ihrer Frage abweichen, aber es hängt mit der Sicherheit Ihres Tokens zusammen, also werde ich es erwähnen. Um einen unbedeutenden Diebstahl des Tokens über die Leitung zu verhindern, möchten Sie den Token wahrscheinlich nicht direkt senden, sondern können den Datenverkehr mit einer HMAC-Funktion signieren. Sie können die Gültigkeit der Nachricht überprüfen, indem Sie die HMAC der Nachricht auf dem Server berechnen und mit der vom Client gesendeten HMAC vergleichen. Sie würden das Token als Schlüssel für die HMAC-Funktion verwenden, damit nur jemand, der das Token kennt, Datenverkehr signieren kann. Dies ist besser für die Sicherheit Ihres Tokens, da Sie es niemals direkt an den Server senden, sodass es nicht direkt abgefangen und gestohlen werden kann. Weitere Informationen zu HMACS finden Sie in dieser Frage: /security/20129/how-and-when-do-i-use-hmac/20301

Keine Sicherheitslösung ist uneinnehmbar. Sie müssen entscheiden, wie viel die Implementierung kosten wird, im Vergleich zu der Wahrscheinlichkeit und den Kosten einer Gefährdung.


Ich kann keine Bibliothek erstellen und darin Geheimnisse ablegen, da diese für jeden meiner Benutzer unterschiedlich sind.
Alok Patel

Zur Verdeutlichung schlug ich vor, dass Sie eine benutzerdefinierte Bibliothek für jeden Ihrer Benutzer erstellen und deren individuelle Geheimnisse in der Bibliothek verbergen könnten. Sie müssten ein System schreiben, um die Bibliotheken bei Bedarf automatisch für jeden neuen Benutzer zu generieren, was möglicherweise mehr Arbeit bedeutet, als Sie tun möchten.
ThePragmatist

0

Zitiere dich selbst:

Ich kann nicht herausfinden, wie der Client / Benutzer authentifiziert werden kann, bei dem er seinen Benutzernamen und sein Kennwort nicht eingeben kann, um sich zu authentifizieren.

Das ist doch ein Widerspruch, oder? ;)

Wie andere gesagt haben, kannst du nicht. Wenn eine App einen API-Schlüssel verwendet, kann man ihn nach Belieben dekompilieren, um die Schlüssel zu erhalten und auch zu verwenden.

Abgesehen davon, dass eine zusätzliche ordnungsgemäße Benutzerauthentifizierung erforderlich ist, können Sie den Schaden nur begrenzen:

  • Whitelisting / Blacklisting von IPs
  • Drosselung
  • Erkennung "ungewöhnlicher Aktivitäten" und deren Quelle
  • einfache Schlüsselerneuerung
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.