Erstellen einer API für mobile Anwendungen - Authentifizierung und Autorisierung

189

Überblick

Ich möchte eine (REST) ​​API für meine Anwendung erstellen. Der ursprüngliche Hauptzweck ist der Verbrauch durch mobile Apps (iPhone, Android, Symbian usw.). Ich habe verschiedene Mechanismen zur Authentifizierung und Autorisierung für webbasierte APIs untersucht (indem ich andere Implementierungen untersucht habe). Ich habe mich mit den meisten grundlegenden Konzepten beschäftigt, suche aber immer noch nach Anleitung in einigen Bereichen. Das Letzte, was ich tun möchte, ist, das Rad neu zu erfinden, aber ich finde keine Standardlösungen, die meinen Kriterien entsprechen (obwohl meine Kriterien falsch sind, können Sie dies auch kritisieren). Außerdem möchte ich, dass die API für alle Plattformen / Anwendungen, die sie verwenden, gleich ist.

oAuth

Ich werde meinen Einwand gegen oAuth zurückwerfen, da ich weiß, dass dies wahrscheinlich die erste angebotene Lösung sein wird. Für mobile Anwendungen (oder insbesondere Nicht-Webanwendungen) scheint es einfach falsch, die Anwendung (um zu einem Webbrowser zu gehen) für die Authentifizierung zu verlassen. Darüber hinaus gibt es (wie mir bekannt ist) keine Möglichkeit für den Browser, den Rückruf an die Anwendung zurückzugeben (insbesondere plattformübergreifend). Ich kenne ein paar Apps, die das tun, aber es fühlt sich einfach falsch an und gibt eine Pause in der Anwendung UX.

Bedarf

  1. Der Benutzer gibt den Benutzernamen / das Passwort in die Anwendung ein.
  2. Jeder API-Aufruf wird von der aufrufenden Anwendung identifiziert.
  3. Der Overhead wird auf ein Minimum reduziert und der Authentifizierungsaspekt ist für Entwickler intuitiv.
  4. Der Mechanismus ist sowohl für den Endbenutzer (ihre Anmeldeinformationen sind nicht verfügbar) als auch für den Entwickler (ihre Anwendungsanmeldeinformationen sind nicht verfügbar) sicher.
  5. Wenn möglich, benötigen Sie kein https (keineswegs eine harte Anforderung).

Meine aktuellen Gedanken zur Implementierung

Ein externer Entwickler fordert ein API-Konto an. Sie erhalten eine Apikey und Apisecret. Für jede Anfrage sind mindestens drei Parameter erforderlich.

  • apikey - wird dem Entwickler bei der Registrierung gegeben
  • Zeitstempel - dient gleichzeitig als eindeutige Kennung für jede Nachricht für eine bestimmte Apikey
  • Hash - ein Hash des Zeitstempels + des Apisecret

Der Apikey muss die Anwendung identifizieren, die die Anfrage ausstellt. Der Zeitstempel verhält sich ähnlich wie oauth_nonce und vermeidet / mildert Wiederholungsangriffe. Der Hash stellt sicher, dass die Anfrage tatsächlich vom Eigentümer des angegebenen Apikey gestellt wurde.

Bei authentifizierten Anforderungen (die im Auftrag eines Benutzers ausgeführt werden) bin ich immer noch unentschlossen, ob ich eine access_token-Route oder eine Kombination aus Benutzername und Kennwort-Hash verwenden möchte. In jedem Fall ist irgendwann eine Kombination aus Benutzername und Passwort erforderlich. Wenn dies der Fall ist, wird ein Hash mit mehreren Informationen (apikey, apisecret, timestamp) + dem Passwort verwendet. Ich würde gerne Feedback zu diesem Aspekt erhalten. Zu Ihrer Information, sie müssten zuerst das Passwort hashen, da ich die Passwörter nicht ohne Hashing in meinem System speichere.

Fazit

Zu Ihrer Information, dies ist keine Anforderung zum Erstellen / Strukturieren der API im Allgemeinen, sondern nur zum Behandeln der Authentifizierung und Autorisierung ausschließlich innerhalb einer Anwendung.

Zufällige Gedanken / Bonusfragen

Wie können Sie bei APIs, für die nur ein Apikey als Teil der Anforderung erforderlich ist, verhindern, dass eine andere Person als der Apikey-Eigentümer den Apikey sehen kann (seitdem im Klartext gesendet), und übermäßige Anforderungen stellen, um sie über die Nutzungsbeschränkungen zu verschieben? Vielleicht denke ich gerade darüber nach, aber sollte es nicht etwas geben, das bestätigt, dass eine Anfrage an den apikey-Besitzer verifiziert wurde? In meinem Fall, das war der Zweck des Apisecret, wird es niemals gezeigt / übertragen, ohne gehasht zu werden.

Apropos Hashes, was ist mit md5 vs hmac-sha1? Ist es wirklich wichtig, wenn alle Werte mit ausreichend langen Daten (dh Apisecret) gehasht werden?

Ich hatte zuvor darüber nachgedacht, meinem Benutzer ein Passwort-Hash pro Benutzer / Zeile hinzuzufügen. Wenn ich das tun würde, wie könnte die Anwendung einen passenden Hash erstellen, ohne das verwendete Salz zu kennen?

jsuggs
quelle
1
Ich hatte gehofft, noch ein paar Kommentare / Vorschläge zu bekommen. Ist die Frage zu vage / mehrdeutig?
Jsuggs
6
Die Frage ist perfekt, aber selbst fast zwei Jahre später scheinen oauth-Implementierungen geheimnisvoll zu sein. Es fällt mir am schwersten, genau das zu erreichen, was Sie oben besprochen haben. Ich habe eine zusätzliche Dimension: Ich möchte kein LoginName / Passwort-Paar verwenden - ich möchte die Google-Identitätsprüfung auf dem Android / iOS verwenden (Symbian wurde vom WWF als "fast ausgestorbene Art" deklariert) und ich weigere mich, mich dafür zu entwickeln Windows Mobile (wie auch immer sie es heutzutage nennen).
Tony Gil
8
Es ist lächerlich, dass so viel wie jeder vorschlägt, noch kein klares, einfaches Tutorial oder Beispiel zu finden, das allgemeines Englisch verwendet, um die Schritte, Anforderungen, Do's und Donts
usw.
2
Lesen Sie diesen speziellen Ablauf von OAuth2.0 (The Resource Owner Password Flow). Keine Weiterleitung zur Website. techblog.hybris.com/2012/06/11/…
Franklin
1
Ich suche auch nach der gleichen Antwort. Ich habe einen guten Artikel gefunden, der kürzlich geschrieben wurde. Ich hoffe das hilft. Stormpath.com/blog/the-ultimate-guide-to-mobile-api-security
Neu bei Rails

Antworten:

44

Die Art und Weise, wie ich darüber nachdenke, den Login-Teil in meinen Projekten durchzuführen, ist:

  1. Vor dem Anmelden fordert der Benutzer eine login_tokenvom Server an. Diese werden auf Anfrage generiert und auf dem Server gespeichert und haben wahrscheinlich eine begrenzte Lebensdauer.

  2. login_tokenUm sich anzumelden, berechnet die Anwendung den Hash des Benutzerkennworts, hasht dann das Kennwort mit dem , um einen Wert zu erhalten, und gibt dann sowohl den login_tokenals auch den kombinierten Hash zurück.

  3. Der Server überprüft die von login_tokenihm generierte Datei und entfernt sie aus seiner Liste der gültigen login_tokens. Der Server kombiniert dann seinen gespeicherten Hash des Benutzerpassworts mit dem login_tokenund stellt sicher, dass er mit dem übermittelten kombinierten Token übereinstimmt. Wenn es übereinstimmt, haben Sie Ihren Benutzer authentifiziert.

Dies hat den Vorteil, dass Sie das Kennwort des Benutzers niemals auf dem Server speichern, das Kennwort niemals im Clear übergeben wird, der Kennwort-Hash nur im Clear bei der Kontoerstellung übergeben wird (obwohl es Möglichkeiten gibt, dies zu umgehen), und dies sollte auch so sein Sicher vor Wiederholungsangriffen, da der login_tokenbei Verwendung aus der Datenbank entfernt wird.

Michael Anderson
quelle
Vielen Dank, ich habe vergessen, den Teil über das Hashing des Passworts auf der Anwendungsseite hinzuzufügen. Ich speichere die Passwörter meiner Benutzer nicht im Klartext (ich habe vor dem Speichern einen Hash).
Jsuggs
2
Ich sehe einen Nachteil dieser Methode: Sie können gesalzene Passwörter nicht in der Datenbank speichern. Wenn Angreifer Ihre Hände auf Ihre Datenbank legen, müssen sie keine Entschlüsselung vornehmen. Da Passwort-Hash das echte Passwort in diesem Schema ist.
Sigod
2
@sigod Du bist richtig. Obwohl ich denke, dass es dort eine grundlegende Zweiteilung gibt - Sie müssen entweder Ihrem Transport vertrauen oder Sie müssen Ihrem Speicher vertrauen. Anmeldesysteme, die gesalzene Passwörter verwenden, vertrauen der Transportschicht - und geben so das Passwort vom Benutzer im Klartext an das Authentifizierungssystem weiter. In diesem Fall wird der Transportschicht nicht vertraut (ich glaube, dies lag daran, dass die Plattform, auf die ich abzielte, SHTTP schlecht unterstützte). Wenn Sie der Transportschicht vertrauen, können Sie möglicherweise andere Kompromisse eingehen.
Michael Anderson
Ich habe 3 Probleme: 1) Wie wird das Passwort des Benutzers nie auf dem Server gespeichert? In Schritt 2 haben Sie erwähnt, dass das Kennwort des gehashten Benutzers gespeichert wird. 2) Das Benutzerkennwort wird niemals im Klartext weitergegeben. Aber es wird tatsächlich auf dem Client gehasht und dann mit dem gehashten Passwort auf dem Server verglichen, was fast dem Übergeben und Speichern im Klartext entspricht. Was bringt das? 3) Diese Methode setzt voraus, dass der Angreifer nicht weiß, wie login_token + password gehasht werden, was gegen das Kerckhoffs-Prinzip verstößt und es wirklich unsicher macht.
Tamer Shlash
14

Das sind eine Menge Fragen in einer, ich denke, einige Leute haben es nicht geschafft, bis zum Ende zu lesen :)

Meine Erfahrung mit der Authentifizierung von Webdiensten ist, dass die Leute sie normalerweise überentwickeln und die Probleme nur die gleichen sind, die Sie auf einer Webseite finden würden. Mögliche sehr einfache Optionen wären https für den Anmeldeschritt, die Rückgabe eines Tokens und die Aufnahme in zukünftige Anforderungen. Sie können auch die http-Basisauthentifizierung verwenden und einfach Inhalte in den Header übergeben. Um die Sicherheit zu erhöhen, drehen / verfallen Sie die Token häufig, überprüfen Sie, ob die Anforderungen vom selben IP-Block stammen (dies kann jedoch unordentlich werden, wenn mobile Benutzer zwischen Zellen wechseln), kombinieren Sie sie mit einem API-Schlüssel oder ähnlichem. Alternativ können Sie den Schritt "Anforderungsschlüssel" von oauth ausführen (jemand hat dies bereits in einer vorherigen Antwort vorgeschlagen und es ist eine gute Idee), bevor Sie den Benutzer authentifizieren, und diesen als erforderlichen Schlüssel zum Generieren des Zugriffstokens verwenden.

Eine Alternative, die ich noch nicht verwendet habe, von der ich aber als gerätefreundliche Alternative zu oAuth viel gehört habe, ist xAuth . Schauen Sie es sich an und wenn Sie es verwenden, wäre ich wirklich interessiert zu hören, was Ihre Eindrücke sind.

Für das Hashing ist sha1 ein bisschen besser, aber lassen Sie sich nicht aufhängen - was auch immer die Geräte einfach (und in Bezug auf die Leistung schnell) implementieren können, ist wahrscheinlich in Ordnung.

Hoffe das hilft, viel Glück :)

Lorna Mitchell
quelle
Danke für die Antwort. Ich habe mich mit xAuth befasst und dies könnte der Weg sein, den ich gehe, damit ich eine oAuth-Installation erhalten kann, die einen standardisierteren Prozess für die Interaktion mit der API ermöglicht.
Jsuggs
9

Was Sie also suchen, ist eine Art serverseitiger Authentifizierungsmechanismus, der die Authentifizierungs- und Autorisierungsaspekte einer mobilen Anwendung behandelt?

Angenommen, dies ist der Fall, würde ich es wie folgt angehen (aber nur, weil ich ein Java-Entwickler bin und ein C # -Typ es anders machen würde):

Der RESTful-Authentifizierungs- und Autorisierungsdienst

  1. Dies funktioniert nur über HTTPS, um ein Abhören zu verhindern.
  2. Es wird auf einer Kombination aus RESTEasy und Spring Security basieren und CAS (für Single Sign-On für mehrere Anwendungen).
  3. Es funktioniert sowohl mit Browsern als auch mit webfähigen Clientanwendungen
  4. Es wird eine webbasierte Kontoverwaltungsoberfläche geben, über die Benutzer ihre Details bearbeiten können, und Administratoren (für bestimmte Anwendungen) können die Berechtigungsstufen ändern

Die clientseitige Sicherheitsbibliothek / -anwendung

  1. Erstellen Sie für jede unterstützte Plattform (z. B. Symbian, Android, iOS usw.) eine geeignete Implementierung der Sicherheitsbibliothek in der Muttersprache der Plattform (z. B. Java, ObjectiveC, C usw.).
  2. Die Bibliothek sollte die HTTPS-Anforderungsbildung unter Verwendung der verfügbaren APIs für die angegebene Plattform verwalten (z. B. verwendet Java URLConnection usw.).
  3. Verbraucher der allgemeinen Authentifizierungs- und Autorisierungsbibliothek (weil das alles ist) codieren auf eine bestimmte Schnittstelle und sind nicht glücklich, wenn sie sich jemals ändern. Stellen Sie daher sicher, dass sie sehr flexibel ist. Befolgen Sie vorhandene Designoptionen wie Spring Security.

Nun, da der Blick aus 30.000 Fuß vollständig ist, wie gehen Sie vor? Nun, es ist nicht so schwer, mit einem Browser-Client ein Authentifizierungs- und Autorisierungssystem zu erstellen, das auf den auf der Serverseite aufgeführten Technologien basiert. In Kombination mit HTTPS bieten die Frameworks einen sicheren Prozess, der auf einem gemeinsam genutzten Token (normalerweise als Cookie dargestellt) basiert, das vom Authentifizierungsprozess generiert und verwendet wird, wann immer der Benutzer etwas tun möchte. Dieses Token wird vom Client dem Server bei jeder Anforderung angezeigt.

Bei der lokalen mobilen Anwendung scheinen Sie nach einer Lösung zu suchen, die Folgendes bewirkt:

  1. Die Clientanwendung verfügt über eine definierte Zugriffssteuerungsliste (Access Control List, ACL), die den Laufzeitzugriff auf Methodenaufrufe steuert. Beispielsweise kann ein bestimmter Benutzer eine Sammlung aus einer Methode lesen, aber seine ACL erlaubt nur den Zugriff auf Objekte, deren Name ein Q enthält, sodass einige Daten in der Sammlung vom Sicherheitsabfangjäger abgerufen werden. In Java ist dies unkompliziert. Verwenden Sie einfach die Spring Security-Annotationen für den aufrufenden Code und implementieren Sie einen geeigneten ACL-Antwortprozess. In anderen Sprachen sind Sie auf sich allein gestellt und müssen wahrscheinlich einen Sicherheitscode für das Boilerplate bereitstellen, der Ihre Sicherheitsbibliothek aufruft. Wenn die Sprache AOP (Aspect Oriented Programming) unterstützt, verwenden Sie es in dieser Situation in vollem Umfang.
  2. Die Sicherheitsbibliothek speichert die vollständige Liste der Berechtigungen für die aktuelle Anwendung im privaten Speicher, damit sie nicht verbunden bleiben muss. Abhängig von der Länge der Anmeldesitzung kann dies ein einmaliger Vorgang sein, der nie wiederholt wird.

Was auch immer Sie tun, versuchen nicht, Ihr eigenes Sicherheitsprotokoll zu erfinden oder Sicherheit durch Unbekanntheit zu verwenden. Sie werden niemals einen besseren Algorithmus dafür schreiben können als die derzeit verfügbaren und kostenlosen. Außerdem vertrauen die Leute bekannten Algorithmen. Wenn Sie also sagen, dass Ihre Sicherheitsbibliothek die Autorisierung und Authentifizierung für lokale mobile Anwendungen mithilfe einer Kombination aus SSL-, HTTPS-, SpringSecurity- und AES-verschlüsselten Token bietet, haben Sie sofort Glaubwürdigkeit auf dem Markt.

Hoffe das hilft und viel Glück bei deinem Vorhaben. Wenn Sie weitere Informationen wünschen, lassen Sie es mich wissen. Ich habe einige Webanwendungen geschrieben, die auf Spring Security, ACLs und dergleichen basieren.

Gary Rowe
quelle
Danke, gute Infos. Ein paar Fragen. Erstens, wenn Abhören akzeptabel ist (nicht sicher, ob es ist / nicht, meine Anwendung enthält keine wirklichen persönlichen / wertvollen Informationen, aber wenn sich meine Begründung ändern würde), ist HTTPS dann tatsächlich erforderlich?
Jsuggs
Sie können das Gesamtsystem außerhalb von HTTPS betreiben, wenn Sie möchten. HTTPS dient nur zum Schutz geheimer Informationen. Daher würde ich davon ausgehen, dass Sie dies während der Authentifizierungsphase über HTTPS tun, um sicherzustellen, dass Ihr Benutzername / Passwort / Geheimnis geheim gehalten wird. Nachdem das Token in der Antwort übergeben wurde, können weitere Anfragen im Klartext gestellt werden, wenn die im Stream enthaltenen Informationen (für deren Erhalt eine Authentifizierung erforderlich war) keinen Schutz vor Abhörern benötigen.
Gary Rowe
Auch diese Beschreibung des CAS-Authentifizierungsprotokolls kann nützlich sein: jasig.org/cas/protocol
Gary Rowe
9

Twitter hat das Problem der externen Anwendung in oAuth behoben, indem es eine von ihnen aufgerufene Variante unterstützt xAuth . Leider gibt es bereits eine Vielzahl anderer Schemata mit diesem Namen, so dass es verwirrend sein kann, dies zu klären.

Das Protokoll ist oAuth, außer dass es die Anforderungs-Token-Phase überspringt und einfach sofort nach Zugriff eines Benutzernamens und eines Kennworts ein Zugriffstoken-Paar ausgibt. (Ab Schritt E hier .) Dies erste Anforderung und Antwort muss gesichert sein- Es sendet den Benutzernamen und das Passwort im Klartext und empfängt das Zugriffstoken und das geheime Token zurück. Sobald das Zugriffstokenpaar konfiguriert wurde, ist es für den Client und den Server für den Rest der Sitzung irrelevant, ob der anfängliche Token-Austausch über das oAuth-Modell oder das xAuth-Modell erfolgte. Dies hat den Vorteil, dass Sie die vorhandene oAuth-Infrastruktur nutzen und nahezu dieselbe Implementierung für mobile / Web- / Desktop-Anwendungen verwenden können. Der Hauptnachteil besteht darin, dass der Anwendung Zugriff auf den Benutzernamen und das Kennwort des Clients gewährt wird. Es scheint jedoch, dass Ihre Anforderungen diesen Ansatz vorschreiben.

Auf jeden Fall möchte ich Ihrer Intuition und der einiger anderer Antwortender hier zustimmen: Versuchen Sie nicht, etwas Neues von Grund auf neu zu bauen. Sicherheitsprotokolle können einfach zu starten sein, sind jedoch immer schwer zu erstellen. Je komplizierter sie sind, desto unwahrscheinlicher ist es, dass Ihre Entwickler von Drittanbietern sie gegen sie implementieren können. Ihr hypothetisches Protokoll ist o (x) Auth sehr ähnlich - api_key / api_secret, nonce, sha1 hashing - aber anstatt eine der vielen vorhandenen Bibliotheken verwenden zu können, müssen Ihre Entwickler ihre eigenen rollen.

Lantius
quelle
2
Ich sollte auch darauf hinweisen, dass es so aussieht, als ob der Endpunkt "Anforderungs-Token überspringen" in oAuth 2 sein wird. Er ist im aktuellen Entwurf als Zugriffsberechtigungstyp "Kennwort" aufgeführt. Siehe Abschnitt 4.1.2: tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.2
lantius
Wie ich gegenüber Lonra erwähnt habe, beschäftige ich mich mehr mit xAuth und speziell aus den Gründen, die Sie am Ende erwähnt haben ... Entwickler können Sie "von der Stange" oAuth-Tools / Bibliotheken verwenden, um mit meiner API zu interagieren, was "eine gute Sache" ist. .
Jsuggs
6

Super spät zur Party, aber ich wollte ein paar zusätzliche Punkte einbringen, die jeder berücksichtigen sollte, der sich für dieses Thema interessiert. Ich arbeite für ein Unternehmen, das mobile API-Sicherheitslösungen ( Approov ) anbietet, sodass dieser gesamte Bereich definitiv für meine Interessen relevant ist.

Zunächst ist es wichtig zu berücksichtigen, wie viel es für Sie wert ist, eine mobile API zu sichern . Die richtige Lösung für eine Bank unterscheidet sich von der richtigen Lösung für jemanden, der Dinge nur zum Spaß macht.

In der vorgeschlagenen Lösung erwähnen Sie, dass mindestens drei Parameter erforderlich sind:

  • apikey - wird dem Entwickler bei der Registrierung übergeben
  • Zeitstempel - dient gleichzeitig als eindeutige Kennung für jede Nachricht für eine bestimmte Apikey
  • Hash - ein Hash des Zeitstempels + des Apisecret

Dies impliziert, dass für einige API-Aufrufe kein Benutzername / Passwort erforderlich ist. Dies kann für Anwendungen nützlich sein, bei denen Sie keine Anmeldung erzwingen möchten (z. B. Surfen in Online-Shops).

Dies ist ein etwas anderes Problem als das der Benutzerauthentifizierung und ähnelt eher der Authentifizierung oder Bescheinigung der Software. Es gibt keinen Benutzer, aber Sie möchten dennoch sicherstellen, dass kein böswilliger Zugriff auf Ihre API erfolgt. Sie verwenden also Ihr API-Geheimnis, um den Datenverkehr zu signieren und den Code, der auf die API zugreift, als echt zu identifizieren. Das potenzielle Problem bei dieser Lösung ist, dass Sie dann das Geheimnis in jeder Version der App preisgeben müssen. Wenn jemand das Geheimnis extrahieren kann, kann er Ihre API verwenden, sich als Ihre Software ausgeben, aber tun, was er will.

Um dieser Bedrohung entgegenzuwirken, können Sie eine Reihe von Maßnahmen ergreifen, je nachdem, wie wertvoll die Daten sind. Die Verschleierung ist ein einfacher Weg, um die Entschlüsselung des Geheimnisses zu erschweren. Es gibt Tools, die dies für Sie tun, insbesondere für Android, aber Sie müssen immer noch Code haben, der Ihren Hash generiert, und eine ausreichend qualifizierte Person kann immer nur die Funktion aufrufen, die das Hashing direkt ausführt.

Eine andere Möglichkeit, die übermäßige Verwendung einer API zu verhindern, für die keine Anmeldung erforderlich ist, besteht darin, den Datenverkehr drosseln und möglicherweise verdächtige IP-Adressen zu identifizieren und zu blockieren. Der Aufwand, den Sie unternehmen möchten, hängt weitgehend davon ab, wie wertvoll Ihre Daten sind.

Darüber hinaus können Sie leicht in die Domäne meines Tagesberufs einsteigen. Wie auch immer, es ist ein weiterer Aspekt der Sicherung von APIs, den ich für wichtig halte und den ich melden wollte.

ThePragmatist
quelle