Design für die Facebook-Authentifizierung in einer iOS-App, die auch auf einen gesicherten Webdienst zugreift

402

Ziel: Ermöglichen Sie einem Benutzer die Authentifizierung mit Facebook in einer iOS-Anwendung, für die Zugriff auf einen geschützten Webdienst erforderlich ist, den ich ausführe.

Annahmen: Es gibt ein natives Authentifizierungs- (und Registrierungs-) System für Benutzer, die sich dafür entscheiden, Facebook nicht für die Anmeldung zu verwenden.

Einzelheiten:

  • Angenommen, wir möchten einem Benutzer die Möglichkeit bieten, sich bei Facebook anzumelden, ohne ein separates Konto / einen separaten Berechtigungsnachweis für unser System zu erstellen.
  • Da wir unseren eigenen nativen Authentifizierungsmechanismus (Benutzername und Kennwort) unterstützen, verfügen wir über eigene Benutzer-IDs und stellen ein Authentifizierungstoken aus, das nach der ersten Überprüfung der Anmeldeinformationen für nachfolgende Interaktionen verwendet wird.

Ich bin überrascht, dass Facebook in seiner Entwicklerdokumentation keine Best Practices dafür hat. In der gesamten vorhandenen Dokumentation wird entweder davon ausgegangen, dass Sie die FB-Authentifizierung in eine Website oder eine eigenständige mobile App ohne Dienst integrieren, für den eine Authentifizierung erforderlich ist.

Hier sind meine ersten Gedanken darüber, wie dies gestaltet werden soll, aber ich möchte überprüfen, ob es korrekt ist.

  1. Client öffnet das Facebook iOS Login
  2. Benutzer der Benutzeroberfläche meldet sich mit Facebook-Anmeldeinformationen an und erhält Zugriffstoken
  3. Die iOS App übergibt das Zugriffstoken an unseren Server
  4. Unser Server kommuniziert mit der FB-Diagramm-API über ein Zugriffstoken, um (a) das Token zu validieren und (b) die FB-Benutzer-ID für dieses Zugriffstoken abzurufen.

    Beispiel: Unser Server würde https://graph.facebook.com/me/?access_token=XYZ aufrufen, wodurch Profilinformationen in einem JSON-Objekt zurückgegeben würden

  5. Unter der Annahme, dass es gültig ist, extrahiert unser Server die Benutzer-ID aus dem JSON-Objekt und prüft, ob der Benutzer bereits ein Konto hat. In diesem Fall stellen wir dem Client unser eigenes Authentifizierungsticket zur Verwendung für diese Sitzung aus. Wenn der Benutzer kein Konto hat, erstellen wir ein neues Konto mit der Facebook-Benutzer-ID, weisen unsere eigene eindeutige Benutzer-ID zu und stellen unser Authentifizierungsticket aus.

  6. Der Client gibt dann das Authentifizierungsticket für nachfolgende Interaktionen zurück, für die eine Authentifizierung erforderlich ist.

Dies scheint mir der richtige Ansatz zu sein, aber ich bin mir nicht sicher, ob mir etwas wahnsinnig Grundlegendes fehlt und ich den falschen (komplizierten) Weg gehe.

TMC
quelle
1
Wie wurde das gelöst? Ich möchte auch das Zugriffstoken übergeben und den Benutzer auf dem Server hochfahren. Scheint akademisch, frage aber.
Chris Van Buskirk
Dies war meine Implementierung mit Rails und Devise: stackoverflow.com/questions/7232490/…
Matt
Warum nicht den gesamten auth_hash übergeben, anstatt zwei Aufrufe an die FB-API ausführen zu müssen (einen vom iOS-Gerät und einen vom Server)?
Bsiddiqui
1
Was ist, wenn Sie sich von einem anderen Gerät aus anmelden möchten (dh Sie haben kein Authentifizierungsticket)? Und wenn Sie nur ein neues Authentifizierungsticket erhalten, was hindert jemanden daran, die Facebook-ID / das Facebook-Token unterwegs zu entführen und auf seinem eigenen Gerät zu verwenden?
Amitloaf
Warum sollten Sie in Schritt 5 aus Neugier Ihr eigenes Authentifizierungsticket ausstellen? Könnten Sie das Facebook-Zugriffstoken nicht für jeden nachfolgenden Serveraufruf verwenden? Mir ist klar, dass für jeden App-> Server-Aufruf ein Aufruf vom Server an die Facebook-API erforderlich ist und nicht nur der erste.
Anders

Antworten:

80

Ich habe mich gerade selbst darum gekümmert, und hier ist der Teil, der mich gebissen hat:

In Schritt 5 ... Es ist möglich, dass sich ein Benutzer für ein Konto bei Ihnen registriert, das völlig unabhängig von seiner Facebook-ID ist, oder? Dann melden sie sich ein anderes Mal bei Facebook an ... Und Sie haben ihnen gerade einen zweiten Account erstellt und ihren ersten verloren.

Es muss eine Möglichkeit geben, sich bei Ihrem Webdienst anzumelden, sich dann bei Facebook anzumelden und die Zuordnung zwischen der Facebook-ID und dem lokalen Konto zu erfassen.

Abgesehen davon klingt Ihr Plan solide.

Update : Facebook hat HIER ein Dokument hinzugefügt, das ein solches Szenario beschreibt

Dan Ray
quelle
7
Ja, ich habe darüber nachgedacht und du bist genau richtig. Wir planen, Konten zusammenzuführen, wenn es sich um dieselbe E-Mail-Adresse handelt. Andernfalls erstellen wir eine andere Möglichkeit, sie zusammenzuführen.
TMC
Welche Serverbibliothek verwenden Sie auf der Serverseite, um die Anforderung zu stellen?
TimLeung
7
@TimLeung - Meines Wissens nach bettet ein Zugriffstoken die App-ID ein und Sie können kein Zugriffstoken OHNE eine darin eingebrannte App-ID haben.
Dan Ray
1
@ TimLeunge: Wir verwenden die Graph-API für Anforderungen mit dem Zugriffstoken des Benutzers.
TMC
29

Verwenden Sie https, um das Authentifizierungstoken an Ihren Server zu übertragen, wie von Facebook angegeben

Freigabe von Zugriffstoken

Unsere Datenrichtlinien verbieten ausdrücklich die Weitergabe eines Zugriffstokens für Ihre App an andere Apps. Wir erlauben Entwicklern jedoch, Tokens zwischen einer nativen Implementierung und einer Serverimplementierung derselben App (dh unter Verwendung derselben App-ID) gemeinsam zu nutzen, solange die Übertragung über HTTPS erfolgt.

zoomcrypt
quelle
16

Ein Problem, das ich bei dieser Strategie sehen kann, ist, dass jemand Ihnen ein Zugriffstoken geben kann, das Sie für eine andere Facebook-App erhalten haben. Soweit ich weiß, gibt es keine Möglichkeit zu überprüfen, ob das Zugriffstoken für Ihre Anwendung bestimmt ist. Sie können es also einfach weiter verwenden.

Es klingt jedoch nicht sehr schädlich. Im Allgemeinen versuchen Personen / Apps, die Zugriffstoken zu schützen, anstatt sie freizugeben.

Ein möglicher Exploit davon wäre, dass jemand seine eigene Site oder mobile App erstellt, Zugriffstoken für seine Benutzer erhält und versucht, diese mithilfe Ihrer API zu authentifizieren. Wenn dies erfolgreich ist (der Benutzer hat ein Facebook-Konto auf Ihrer Site), kann die böswillige Site Ihre API verwenden, die sich als Benutzer ausgibt.

Es ist ein bisschen langwierig, aber ich denke, es könnte funktionieren.

Bearbeiten: Es sieht so aus, als gäbe es doch eine Möglichkeit, das Zugriffstoken zu validieren. Siehe die Antwort von @Daaniel auf Frage Abrufen der Anwendungs-ID vom Benutzerzugriffstoken (oder Überprüfen der Quellanwendung für ein Token) .

ivant
quelle
Senden appsecret_proofsollte dies verhindern (siehe hier )
Tony
@ Tony kannst du erklären wie das appsecret_proofhier hilft? Soweit ich weiß, dient dies dazu, Facebook zu beweisen, dass der Server den geheimen Schlüssel kennt. Ivant bezog sich jedoch auf eine böswillige App, die Token abruft und diese dann an Ihre API sendet. Der Server kann die App-ID überprüfen, aber die App-ID kann leicht von einer böswilligen App gefälscht werden. Also ... wie würde man das abmildern?
YSK
3
Sie können überprüfen, ob das Token für Ihre App generiert wurde, über https://graph.facebook.com/app/?access_token=[user_access_token]das die App-ID zurückgegeben wird, und dann die App-IDs vergleichen
Nader Alexan
4

Ihre Lösung funktioniert völlig.

Vielleicht eine Alternative: Warum nicht einfach die E-Mail des Kunden von der ersten Anfrage nach einem sozialen Dienst abrufen und an Ihren Webdienst senden? Der Webdienst könnte nur die E-Mail speichern und möglicherweise auch einen social_provider. Ich verstehe, dass Ihr Webdienst nicht überprüfen kann, woher die E-Mail stammt, aber besteht keine vertrauensvolle Beziehung zwischen Ihrem Webdienst und Ihrem Kunden? Wenn ja, können Sie sich anscheinend darauf verlassen, dass die E-Mail vom richtigen Ort kommt. Jemand, bitte lassen Sie mich wissen, was mir offensichtlich fehlt, was den E-Mail-basierten Ansatz albern macht ...

hamsterdam
quelle
3
Ich konnte leicht herausfinden, wie der Client mit dem Server spricht. Dann könnte ich einfach E-Mails darauf werfen, bis ich einen Treffer bekomme. Es muss immer irgendeine Form der Überprüfung geben
Chris
5
Hohes Vertrauen und Kunde? Bitte niemals im selben Satz. Außer dem vorherigen Satz natürlich.
EralpB