Sichern der REST-API meiner Node.js-App?

68

Ich könnte etwas Hilfe für meine REST-API gebrauchen. Ich schreibe eine Node.js-App, die Express und MongoDB verwendet und Backbone.js auf der Clientseite hat. Ich habe die letzten zwei Tage damit verbracht, all das herauszufinden und nicht viel Glück zu haben. Ich habe bereits ausgecheckt:

Ich möchte mein Backend und Frontend so getrennt wie möglich halten, daher habe ich mir überlegt, eine sorgfältig gestaltete REST-API zu verwenden. Ich denke, wenn ich jemals eine iPhone-App (oder etwas Ähnliches) entwickeln sollte, könnte sie die API verwenden, um auf Daten zuzugreifen.

ABER ich möchte, dass dies sicher ist. Ein Benutzer hat sich bei meiner Web-App angemeldet und ich möchte sicherstellen, dass meine API sicher ist. Ich habe über OAuth, OAuth 2.0, OpenID, Hmac, Hashes usw. gelesen. Ich möchte die Verwendung der externen Anmeldung (Facebook / Twitter / usw.) vermeiden. Ich möchte, dass sich die Registrierung und Anmeldung auf meiner App / meinem Server befindet.

... aber ich bin hier immer noch verwirrt. Vielleicht ist es spät in der Nacht oder mein Gehirn ist nur gebraten, aber ich könnte wirklich ein paar Schritte tun, was ich hier tun soll. Was sind die Schritte für mich, um eine sichere API zu erstellen?

Jede Hilfe, jede Information, jedes Beispiel, jeder Schritt oder irgendetwas wäre großartig. Bitte helfen Sie!

littlejim84
quelle
Was hast du am Ende gemacht?
Morteza Shahriari Nia

Antworten:

28

Hier ist eine andere Art, darüber nachzudenken:

Nehmen wir für einen Moment an, dass Sie keine API verwenden. Ihr Benutzer meldet sich bei der App mit einigen Anmeldeinformationen an und Sie geben dem Benutzer ein Cookie oder ein ähnliches Token, mit dem Sie identifizieren, dass sich der Benutzer angemeldet hat. Der Benutzer fordert dann eine Seite mit eingeschränkten Informationen an (oder erstellt / Ändern / Löschen), damit Sie dieses Token überprüfen, um sicherzustellen, dass der Benutzer diese Informationen anzeigen darf.

Nun scheint es mir, dass das einzige, was Sie hier ändern, die Art und Weise ist, wie Informationen geliefert werden. Anstatt die Informationen als gerendertes HTML bereitzustellen, geben Sie die Informationen als JSON zurück und rendern sie auf der Clientseite. Ihre AJAX-Anforderungen an den Server enthalten dasselbe angemeldete Token wie zuvor. Ich empfehle daher, nur dieses Token zu überprüfen und die Informationen auf die gleiche Weise auf "genau das zu beschränken, was der Benutzer wissen darf".

Ihre API ist jetzt so sicher wie Ihre Anmeldung. Wenn jemand das für den Zugriff auf die API erforderliche Token kennen sollte, würde er auch auf der Site angemeldet sein und trotzdem Zugriff auf alle Informationen haben. Das Beste ist, wenn Sie die Anmeldung bereits implementiert haben, mussten Sie nicht mehr wirklich arbeiten.

Bei Systemen wie OAuth geht es darum, diese Anmeldemethode bereitzustellen, normalerweise von einer Drittanbieteranwendung und als Entwickler. Dies wäre möglicherweise eine gute Lösung für eine iPhone-App oder ähnliches, aber das ist in der Zukunft. Es ist nichts Falsches daran, dass die API mehr als eine Authentifizierungsmethode akzeptiert!

mjtamlyn
quelle
Also denke ich nur darüber nach, nehme ich an? Ich habe bereits eine "normale" Authentifizierung im Gange ... Der Benutzer meldet sich an, es wird ein Cookie für die Sitzung erstellt und die Site überprüft, ob der Benutzer für die verschiedenen "sicheren" Teile angemeldet ist. Also im Wesentlichen, das ist es!? ... Ich überdenke nur das Problem und versuche, mit OAuth usw. umzugehen, aber in Wirklichkeit ist es immer noch nur das grundlegende Authentifizierungsmaterial ... Nun, wenn es das ist, dann ist das in Ordnung! Ich nehme an, wenn überhaupt, muss ich SSL auf meinem Server sortieren lassen, aber ansonsten kann ich einfach meine normale Authentifizierungsprozedur verwenden?
littlejim84
1
Es könnte sein, dass mir hier etwas fehlt, aber verstößt diese Art nicht gegen die Kapitalregel von APIs? Dh kein serverseitiger Zustand? Wenn der Server die Token im Auge behalten muss, bedeutet dies, dass der Status gehalten wird, was ein bisschen ein Nein-Nein sein sollte :-)
Dieter
2
@Dieter es ist staatenlos, dass der Staat nicht in der http
Typo Johnson
2
@dieter Die Token können so konstruiert werden, dass die Server keine Datenbank mit ausgegebenen Token verwalten müssen, um ein Token zu validieren. Signieren Sie das Token mit einem privaten Schlüssel, damit jeder mit dem passenden öffentlichen Schlüssel überprüfen kann, ob a) das Token von einem vertrauenswürdigen Server ausgestellt wurde (Authentizität) und b) das Token nicht geändert wurde (Wiedergabetreue). Das Token sind die Statusdaten, sodass der Server zustandslos sein kann. OAuth2 definiert nicht den Inhalt eines Tokens, sondern nur, wie man einen erhält. JSON Web Tokens (JWT) definieren ein sicheres Token-Format, das mit OAuth2 verwendet werden kann.
Dthorpe
1
@dthorpe Danke! Das macht Sinn. TypoJohnson, Ich bin mir ziemlich sicher, dass dies nicht zustandslos in APIs bedeutet. Statuslos = Die API kann jede Anfrage bearbeiten, ohne sich an etwas erinnern zu müssen. Damit spielt es keine Rolle, ob Server 2 einen Client verarbeitet, der vor einer Minute von Server 1 bedient wurde. In einigen Fällen ist es also in Ordnung, einen Status im http (vom Client) übergeben zu haben. Und wenn es nicht möglich ist, müssen sie nur eine
Dieter
39

In der Reihenfolge zunehmender Sicherheit / Komplexität:

Grundlegende HTTP-Authentifizierung

In vielen API-Bibliotheken können Sie dies einbauen (z. B. Piston in Django) oder Ihren Webserver damit umgehen lassen. Sowohl Nginx als auch Apache können Serveranweisungen verwenden, um eine Site mit einem einfachen b64-codierten Kennwort zu sichern. Es ist nicht die sicherste Sache der Welt, aber es ist mindestens ein Benutzername und ein Passwort!

Wenn Sie Nginx verwenden, können Sie Ihrer Host-Konfiguration einen Abschnitt wie folgt hinzufügen:

auth_basic "Restricted";
auth_basic_user_file /path/to/htpasswd;

(Steck es in deinen location /Block)

Dokumente: http://wiki.nginx.org/HttpAuthBasicModule

Sie benötigen das Python-Skript, um dieses Kennwort zu generieren und die Ausgabe in eine Datei zu speichern: http://trac.edgewall.org/browser/trunk/contrib/htpasswd.py?format=txt

Der Speicherort der Datei spielt keine große Rolle, solange Nginx Zugriff darauf hat.

HTTPS

Sichern Sie die Verbindung von Ihrem Server zur App. Dies ist die grundlegendste und verhindert Angriffe von Menschen in der Mitte.

Sie können dies mit Nginx tun, die Dokumente dafür sind sehr umfassend: http://wiki.nginx.org/HttpSslModule

Ein selbstsigniertes Zertifikat hierfür wäre in Ordnung (und kostenlos!).

API-Schlüssel

Diese können in einem beliebigen Format vorliegen, bieten jedoch den Vorteil, dass Sie den Zugriff bei Bedarf widerrufen können. Möglicherweise nicht die perfekte Lösung für Sie, wenn Sie beide Enden der Verbindung entwickeln. Sie werden in der Regel verwendet, wenn Dritte die API verwenden, z. B. Github.

OAuth

OAuth 2.0 ist das Richtige für Sie. Obwohl ich die zugrunde liegende Funktionsweise der Spezifikation nicht kenne, ist sie derzeit der Standard für die meisten Authentifizierungen (Twitter, Facebook, Google usw.), und es gibt eine Menge Bibliotheken und Dokumente, die Ihnen bei der Implementierung helfen. Davon abgesehen wird es normalerweise verwendet, um einen Benutzer zu authentifizieren, indem ein Drittanbieter nach der Authentifizierung gefragt wird.

Angesichts der Tatsache, dass Sie die Entwicklung an beiden Enden durchführen, würde es wahrscheinlich ausreichen, Ihre API hinter Basic HTTP Auth zu stellen und über HTTPS bereitzustellen, insbesondere wenn Sie keine Zeit damit verschwenden möchten, mit OAuth herumzuspielen.

Ghickman
quelle
Gute Antwort. Ich sehe, dass OAuth der Standard zu sein scheint. Aber es scheint 2-beiniges OAuth 1.0, 3-beiniges OAuth 1 und dann dieses OAuth 2 zu geben ... Also sollte ich mir OAuth 2 ansehen? ... Ich habe an HTTPS / SSL gedacht, bin mir aber nicht sicher, wie so etwas wie eine iPhone-App darüber übertragen könnte (ist das überhaupt möglich)? ... eine andere Frage bei OAuth: Kann ich sowohl Anbieter als auch Verbraucher sein oder muss ich - wie Sie sagen - einen Drittanbieter zur Authentifizierung verwenden? In dieser Situation wäre die Verwendung eines Drittanbieters nicht zu bevorzugen, es ist nicht wirklich diese Art von App. Danke für die ausführliche Antwort!
littlejim84
OAuth 2 ist das aktualisierte OAuth. Ich glaube, 1.0 wird jetzt als "schlecht" angesehen. Das iPhone funktioniert definitiv über HTTPS (Github in Mobile Safari!).
Ghickman
Sie können beides sein, aber normalerweise wird OAuth zur Authentifizierung mit einem Drittanbieter verwendet. Wie @mjtamlyn weiter unten ausgeführt hat, ist die Verwendung Ihres aktuellen Authentifizierungssystems sicherlich eine Möglichkeit. Ich habe meine Antwort mit einigen Schritten für einige der Teile aktualisiert.
Ghickman
Danke für die Antwort! Das hat mir viele Informationen gegeben, die ich verarbeiten kann, da all dieses
Authentifizierungsmaterial
1
Ich bin gerade auf diesen Artikel gestoßen, der kurz OAuth1 und OAuth2 Stormpath.com/blog/secure-your-rest-api-right-way
Fabian Leutgeb
0

Tipps zum Sichern von Webanwendungen

Wenn Sie Ihre Anwendung sichern möchten, sollten Sie auf jeden Fall HTTPS anstelle von HTTP verwenden . Dies stellt sicher, dass ein sicherer Kanal zwischen Ihnen und den Benutzern erstellt wird, der verhindert, dass die an die Benutzer gesendeten Daten abgehört werden, und dass die Daten erhalten bleiben vertraulich ausgetauscht.

Sie können JWTs (JSON Web Tokens) verwenden, um RESTful-APIs zu sichern . Dies hat im Vergleich zu serverseitigen Sitzungen viele Vorteile. Die Vorteile sind hauptsächlich:

1- Skalierbarer, da Ihre API-Server nicht für jeden Benutzer Sitzungen verwalten müssen (was bei vielen Sitzungen eine große Belastung sein kann).

2- JWTs sind in sich geschlossen und haben die Ansprüche, die zum Beispiel die Benutzerrolle definieren und auf die er zugreifen kann und die zum Datum und Ablaufdatum ausgestellt wurden (danach ist JWT nicht mehr gültig)

3- Einfachere Handhabung über Load-Balancer hinweg. Wenn Sie über mehrere API-Server verfügen, müssen Sie weder Sitzungsdaten freigeben noch den Server so konfigurieren, dass die Sitzung an denselben Server weitergeleitet wird, wenn eine Anforderung mit einem JWT einen Server trifft, kann diese authentifiziert werden & autorisiert

4- Weniger Druck auf Ihre Datenbank und Sie müssen nicht ständig Sitzungs-IDs und -Daten für jede Anforderung speichern und abrufen

5- Die JWTs können nicht manipuliert werden, wenn Sie einen starken Schlüssel zum Signieren der JWT verwenden. Sie können also den Ansprüchen in der JWT vertrauen, die mit der Anfrage gesendet werden, ohne die Benutzersitzung überprüfen zu müssen und ob er autorisiert ist oder nicht Sie können einfach die JWT überprüfen und dann wissen Sie, wer und was dieser Benutzer tun kann.

Node.js spezifische Bibliotheken zur Implementierung von JWTs:

Viele Bibliotheken bieten einfache Möglichkeiten zum Erstellen und Validieren von JWTs, zum Beispiel: In node.js ist jsonwebtoken eine der beliebtesten. Sie können auch zur Validierung der JWTs dieselbe Bibliothek verwenden oder express-jwt oder koa-jwt verwenden (falls vorhanden) mit Express / Koa)

Da REST-APIs im Allgemeinen darauf abzielen, den Server zustandslos zu halten, sind JWTs mit diesem Konzept besser kompatibel, da jede Anforderung mit einem eigenständigen Autorisierungstoken (JWT) gesendet wird, ohne dass der Server die Benutzersitzung im Vergleich zu Sitzungen, in denen der Server ausgeführt wird, verfolgen muss Server statusbehaftet, damit er sich an den Benutzer und seine Rolle erinnert. Sitzungen sind jedoch auch weit verbreitet und haben ihre Vorteile, nach denen Sie suchen können, wenn Sie möchten.

Eine wichtige Sache, die Sie beachten sollten, ist, dass Sie das JWT mithilfe von HTTPS sicher an den Client senden und an einem sicheren Ort speichern müssen (z. B. im lokalen Speicher).

Weitere Informationen zu JWTs finden Sie unter diesem Link

Ahmed Elkoussy
quelle