REST-API für Websites, die Facebook zur Authentifizierung verwenden

85

Wir haben eine Website, auf der Sie sich nur mit Facebook anmelden und authentifizieren können (dies war nicht meine Wahl). Wenn Sie sich zum ersten Mal bei Facebook anmelden, wird automatisch ein Konto für Sie erstellt.

Wir möchten jetzt eine iPhone-Anwendung für unsere Website und eine öffentliche API erstellen, damit andere unseren Service nutzen können.

Diese Frage bezieht sich auf die Authentifizierung mit unserer Website über die App / API und ist in zwei Teile unterteilt:

  1. Wie kann die REST-Authentifizierung von einer API zu einer Website, die nur Facebook OAuth als Authentifizierungsmethode verwendet, korrekt verarbeitet werden?

    Ich habe viel über Standardauthentifizierungsmethoden für die REST-API gelesen und recherchiert. Methoden wie Basic Auth over HTTPS können nicht verwendet werden , da für einen Benutzer als solchen keine Anmeldeinformationen vorhanden sind. So etwas wie dies scheint für die Authentifizierung von Anwendungen mit der API nur zu sein.

    Derzeit ist der beste Weg, den ich mir vorstellen kann, dass Sie einen / authorize-Endpunkt in unserer API erreichen, dieser zu Facebook OAuth umleitet, dann zurück zur Site leitet und ein "Token" bereitstellt, mit dem sich der Benutzer der API anschließend authentifizieren kann Anfragen.

  2. Für eine offizielle Anwendung, die wir erstellen, müssten wir die öffentliche API nicht unbedingt auf die gleiche Weise verwenden. Was wäre dann der beste Weg, um mit unserer Website zu sprechen und Benutzer zu authentifizieren?

Ich verstehe (glaube ich), wie Anwendungen von Drittanbietern, die unsere API verwenden, mithilfe von API-Schlüsseln (öffentlich) und geheimen Schlüsseln (privat) authentifiziert werden. Wenn es jedoch um die Authentifizierung des Benutzers geht, der die App verwendet, bin ich ziemlich verwirrt darüber, wie ich vorgehen soll, wenn wir einen Benutzer nur auf Facebook authentifizieren müssen.

Ich habe das Gefühl, dass mir etwas sehr Offensichtliches fehlt oder ich nicht vollständig verstehe, wie öffentliche REST-APIs funktionieren sollten. Daher wäre jeder Rat und jede Hilfe sehr dankbar.

Adam
quelle
Ich habe eine ähnliche Frage unter stackoverflow.com/questions/30230482/… , die über einige davon spricht
JVK

Antworten:

98

UPDATE: siehe unten

Ich habe auch über diese Frage nachgedacht. Es ist mir noch nicht ganz klar, aber hier ist der Weg, den ich einschlagen möchte. Ich erstelle eine REST-API und meine Benutzer authentifizieren sich nur mit Facebook Connect.

Auf dem KUNDEN:

  1. Verwenden Sie die Facebook-API, um sich anzumelden und einen OAUTH2-Code zu erhalten.
  2. Tauschen Sie diesen Code gegen ein Zugriffstoken aus.
  3. Bei jedem Aufruf meiner benutzerdefinierten API werde ich die Facebook-Benutzer-ID und das Zugriffstoken angeben.

Auf der API (für jede Methode, die eine Benutzerauthentifizierung erfordert):

  1. Stellen Sie mit dem Zugriffstoken von oben eine Anfrage an das / me Facebook-Diagramm.
  2. Stellen Sie sicher, dass die zurückgegebene Facebook-Benutzer-ID mit der von oben an meine API übergebenen Benutzer-ID übereinstimmt.
  3. Wenn das Zugriffstoken abgelaufen ist, ist zusätzliche Kommunikation erforderlich.

Ich muss das noch testen. Wie hört es sich an?

--- Update: 27. Juli 2014 zur Beantwortung der Frage ---

Ich benutze den oben genannten Austausch nur einmal beim Anmelden. Sobald ich festgestellt habe, welcher Benutzer sich anmeldet, erstelle ich mein eigenes Zugriffstoken, und dieses Token wird ab diesem Zeitpunkt verwendet. Der neue Flow sieht also so aus ...

Auf dem KUNDEN:

  1. Verwenden Sie die Facebook-API, um sich anzumelden und einen OAUTH2-Code zu erhalten.
  2. Tauschen Sie diesen Code gegen ein Zugriffstoken aus.
  3. Fordern Sie ein Zugriffstoken von meiner API an, einschließlich des Facebook-Tokens als Parameter

Auf der API

  1. Zugriffstoken-Anfrage erhalten.
  2. Stellen Sie mit dem Facebook-Zugriffstoken eine Anfrage an das / mich Facebook-Diagramm
  3. Stellen Sie sicher, dass der Facebook-Benutzer vorhanden ist und mit einem Benutzer in meiner Datenbank übereinstimmt
  4. Erstellen Sie mein eigenes Zugriffstoken, speichern Sie es und senden Sie es an den Client zurück, damit es ab diesem Zeitpunkt verwendet werden kann
Chris Greenwood
quelle
Hey, das ist eine Art späte Antwort, aber Ihre Lösung scheint das Problem zu beheben, das ich in meiner ersten Antwort hatte. Natürlich müssten Sie HTTPS verwenden, um das Paar (id, token) nicht im Klartext auf dem Draht zu senden. Aber es sieht so aus, als sollte es funktionieren!
Olivier Lance
Ich denke, es ist gut, mich auf dem Server anzurufen und ein eigenes Zugriffstoken zu generieren, das vom mobilen Client verwendet wird.
Der_Meister
Ich fand, dass es eine schlechte Praxis ist, FB geheim in der mobilen App zu speichern. Facebook empfiehlt, es nur auf Ihrem Server zu speichern. developer.facebook.com/docs/opengraph/using-actions/…
Der_Meister
Wenn wir user_id und access_token jedes Mal an den API-Server senden (als post / get-Parameter). Wird es eine Sicherheitslücke schaffen, wenn jemand die Verbindung abfangen kann?
Nathan Do
@NathanDo Verwenden Sie HTTPS zwischen Ihrem Client und dem API-Server. Es sollte kein Problem sein, wenn jemand die Verbindung abfängt (abgesehen von Schwachstellen vom Typ Heartbleed).
dcr
14

Dies ist meine Implementierung mit JWTs (JSON Web Tokens), die im Grunde der aktualisierten Antwort von Chris ähnelt. Ich habe Facebook JS SDK und JWT verwendet.

Hier ist meine Implementierung.

  1. Client: Verwenden Sie das Facebook JS SDK, um sich anzumelden und das Zugriffstoken zu erhalten.

  2. Client: Fordern Sie JWT von meiner API an, indem Sie den /verify-access-tokenEndpunkt aufrufen .

  3. MyAPI: Empfängt das Zugriffstoken und überprüft es, indem Sie den /meEndpunkt der Facebook-API aufrufen .

  4. MyAPI: Wenn das Zugriffstoken gültig ist, findet der Benutzer aus der Datenbank und meldet den Benutzer an, falls vorhanden. Erstellen Sie eine JWT mit den erforderlichen Feldern als Nutzdaten, legen Sie einen Ablauf fest, signieren Sie mit dem geheimen Schlüssel und senden Sie ihn an den Client zurück.

  5. Client: Speichert das JWT im lokalen Speicher.

  6. Client: Sendet das Token (das JWT aus Schritt 5) zusammen mit der Anforderung für den nächsten API-Aufruf.

  7. MyAPI: Überprüfen Sie das Token mit dem geheimen Schlüssel. Wenn das Token gültig ist, tauschen Sie das Token gegen ein neues aus und senden Sie es zusammen mit der API-Antwort an den Client zurück. (Keine externe API fordert hier nachher eine Überprüfung des Tokens an.) [Wenn das Token ungültig ist / abgelaufen ist, fordern Sie den Client an, sich erneut zu authentifizieren und von 1 zu wiederholen.]

  8. Client Ersetzt das gespeicherte Token durch das neue und verwendet es für den nächsten API-Aufruf. Sobald der Token-Ablauf erreicht ist, läuft der Token ab und widerruft den Zugriff auf die API.

Jeder Token wird einmal verwendet.

Lesen Sie weitere Antworten zu Sicherheit und JWT

Wie sicher ist JWT?

Wenn Sie JWT dekodieren können, wie sind sie sicher?

JSON Web Tokens (JWT) als Benutzeridentifikations- und Authentifizierungstoken

Alles ist gut
quelle
3
Ich denke, # 3 sollte eher sein /debug_token, damit Sie überprüfen können, ob das Token tatsächlich für Ihre Anwendung ist.
Peppe LG
2
Nicht access_tokenim Client anfordern . Verwenden Sie "Code Workflow". Pass codezu MyApi und machen eine weitere Runde Reise Book zum Austausch codemit access_token. Dies wird hier ausführlicher erklärt: developer.facebook.com/docs/facebook-login/security
omikron
5

Ich versuche die gleiche Frage zu beantworten und habe in letzter Zeit viel gelesen ...

Ich werde "die" Antwort nicht haben, aber die Dinge werden für mich etwas klarer. Haben Sie die Kommentare in dem Artikel gelesen, den Sie erwähnt haben ? Ich fand sie sehr interessant und hilfreich.

Infolgedessen und angesichts der Entwicklung der Dinge seit dem Schreiben des ersten Artikels denke ich, dass ich Folgendes tun werde:

  • HTTPS überall - so können Sie HMAC, Signieren, Nonce, ... vergessen.

  • Verwenden Sie OAuth2:

    • Wenn Authentifizierungsanforderungen von meinen eigenen Apps / Websites stammen, verwenden Sie diesen Trick (oder eine Variation davon), der in einer Antwort auf den zuvor genannten Artikel beschrieben ist .

    • In meinem Fall habe ich zwei Arten von Benutzern: diejenigen mit klassischen Anmelde- / Kennwortanmeldeinformationen und diejenigen, die sich bei Facebook Connect angemeldet haben.
      Daher würde ich ein reguläres Anmeldeformular mit der Schaltfläche "Mit Facebook anmelden" bereitstellen. Wenn sich der Benutzer mit seinen "klassischen" Anmeldeinformationen anmeldet, sende ich diese einfach mit einem an meinen OAuth2-Endpunkt grant_type=password.
      Wenn er sich über Facebook anmeldet, ist das meiner Meinung nach ein zweistufiger Prozess:

      • Verwenden Sie zunächst das Facebook iOS SDK, um eine FBSession zu öffnen
      • Wenn dies erledigt ist und die App die Kontrolle zurückerhält, sollte es eine Möglichkeit geben, eine Facebook-ID für diesen Benutzer zu erhalten. Ich würde diese ID alleine an meinen OAuth2-Endpunkt mit einer Erweiterungsgewährung senden , die von meinem Server als "Verwenden einer FB-Benutzer-ID" verstanden wird.

Bitte beachten Sie, dass ich immer noch intensiv an all diesen Dingen recherchiere, so dass dies möglicherweise keine perfekte Antwort ist ... vielleicht nicht einmal eine richtige! Aber ich denke, das wäre ein guter Ausgangspunkt. Die Idee, einen "Verlängerungszuschuss" für die Facebook-Authentifizierung zu verwenden, könnte darin bestehen, ihn registrieren zu müssen, um die Dinge richtig zu machen? Ich bin mir nicht ganz sicher.

Wie auch immer, ich hoffe, ich konnte Ihnen sogar ein bisschen helfen und zumindest kann es eine Diskussion beginnen, um die beste Lösung für dieses Problem zu finden :)

Update
Das Facebook-Login ist keine Lösung, wie in den Kommentaren angegeben: Jeder kann eine beliebige Benutzer-ID senden und sich als dieser Benutzer in der API anmelden.

Was ist damit:

  • Zeigen Sie ein Anmeldeformular mit der Schaltfläche "Facebook-Anmeldung" an
  • Wenn diese Anmeldemethode ausgewählt ist, verhalten Sie sich wie beim Facebook SDK: Öffnen Sie eine Webseite von Ihrem Authentifizierungsserver, die die Facebook-Anmeldung initiiert.
  • Sobald sich der Benutzer angemeldet hat, verwendet Facebook Ihre Weiterleitungs-URL zur Bestätigung. Lassen Sie diese URL auf einen anderen Endpunkt Ihres Authentifizierungsservers verweisen (möglicherweise mit einem zusätzlichen Parameter, der angibt, dass der Anruf von einer App kam?)
  • Wenn der Authentifizierungsendpunkt erreicht wird, kann die Authentifizierung den Benutzer sicher identifizieren, seine FB-Benutzer-ID / FB-Sitzung beibehalten und ein Zugriffstoken mithilfe eines benutzerdefinierten URL-Schemas an Ihre App zurückgeben, genau wie dies das Facebook SDK tun würde

Sieht besser aus?

Olivier Lance
quelle
1
Danke für Ihre Antwort! Ich hatte über das meiste nachgedacht, was Sie gesagt haben, aber das Hauptanliegen bei der Verwendung des FB iOS SDK und dem anschließenden Senden der Facebook-Benutzer-ID war, dass es nicht einfach wäre, eine gewünschte ID an Ihren API-Endpunkt zu senden und zu behaupten, dies zu sein Ein anderer Benutzer? Hier stecke ich normalerweise fest.
Adam
Tatsächlich! Das war dumm von mir, nicht darüber nachzudenken ... Also muss die Lösung irgendwie über Ihren eigenen Authentifizierungsserver gehen ...
Olivier Lance
Ich habe meine Antwort mit einer anderen Lösungsidee aktualisiert ... aber gerade festgestellt, dass Sie sie in Ihrer ursprünglichen Frage erwähnt haben! Ich kann im Moment nichts anderes sehen ...
Olivier Lance