Viele Webanwendungen bestehen heutzutage aus einem JavaScript-Frontend (Angular, React, Svelte usw.) und einem separaten Backend. Eine der beliebtesten Backend-Optionen sind REST-APIs. Die meisten der Webanwendungen, die wir für einen unserer Kunden entwickeln, nutzen auch REST-APIs im Backend. Einer der Hauptvorteile von REST-APIs ist die Möglichkeit, die schwere Arbeit der Zugriffskontrolle auf die Backend-Seite zu verlagern. Dies geschieht mit Hilfe der HATEOAS – Beschränkung (Hypermedia As the Engine of Application State), die Teil der einheitlichen Schnittstellenbeschränkung von REST-APIs ist.
HATEOAS und Zugriffskontrolle
Da REST die dem World Wide Web zugrunde liegende Architektur ist, findet sich ein Beispiel für HATEOAS auf praktisch jeder Website, auf die mit einem Standard-Webbrowser zugegriffen werden kann. Beim Zugriff auf eine Website kann der Zustand nur durch Anklicken der eingebetteten Hyperlinks geändert oder gesteuert werden. Es ist möglich, alle Übergänge der Website mit einem Zustandsautomaten zu visualisieren. Dies gilt sowohl für statische Websites als auch für dynamisch generierte Websites. Bei dynamisch generierten Websites können die Zustandsautomaten für jeden Benutzer, der auf die Seite zugreift, unterschiedlich sein. Hier spielt die Zugriffskontrolle in der Regel eine Rolle, da normalerweise nicht jeder Benutzer den gleichen Zugriff auf alle Ressourcen einer Webanwendung hat.
Zur Veranschaulichung können wir eine einfache Blogging-Website nehmen. Es gibt zwei Arten von Benutzern: Der Eigentümer des Blogs und die Besucher, die die Blogeinträge lesen wollen. Während der Eigentümer des Blogs die Möglichkeit haben sollte, Einträge auf dieser Seite zu erstellen, zu löschen oder zu aktualisieren, sollten Besucher die Einträge nur lesen können. Unter der Annahme, dass Authentifizierung und Autorisierung bereits korrekt implementiert sind, lauten die beiden Zustandsautomaten für Benutzer wie folgt:
Jeder Knoten des Zustandsautomaten stellt einen Zustand dar, der vom Server bei einem Seitenbesuch zurückgegeben wird. Die ausgehenden Kanten jedes Knotens zeigen, was ein Benutzer auf der Grundlage seines aktuellen Zustands tun kann. Jede dieser Kanten wird technisch durch einen Link dargestellt. Fehlt eine Kante/ein Link im Zustandsautomaten, bedeutet dies, dass der Benutzer nicht denselben Weg einschlagen darf wie ein anderer Benutzer. Wie der Zustandsautomat andeutet, kann ein Gast keine Ressource verändern, während dem Eigentümer alle Operationen erlaubt sind.
Herkömmliche Websites antworten mit einem HTML-Payload, den die Browser bereits darstellen können. So wird eine Schaltfläche, die nicht in der HTML-Antwort enthalten ist, nicht auf dem Bildschirm angezeigt. Dies könnte auf die Entscheidung des Backends zurückzuführen sein, dass ein Benutzer nicht über ausreichende Rechte verfügt. REST-APIs antworten jedoch in der Regel mit einer Art von JSON-Nutzdaten. Bei der Anwendung von HATEOAS wird diese Nutzlast in irgendeiner Form eine Liste von Links enthalten, die dem Client mitteilt, was er als nächstes tun darf. In diesem Fall muss das Frontend eine Logik implementieren, um die gleiche dynamische Darstellung der Benutzeroberfläche zu erreichen. Im nächsten Abschnitt werden wir ein kurzes Beispiel zeigen, wie wir die Frontend-seitige Zugriffskontrolle in Svelte erreichen.
Beispiel in Svelte
Angenommen, das folgende Antwortobjekt wird von einer REST-API zurückgegeben, nachdem eine einzelne Beispielressource angefordert wurde (Links werden mit einer proprietären reservierten Eigenschaft implementiert):
const response = {
“xxx”: “data XXX”,
“yyy”: “data YYY”,
“_links”: {
“self”: “https://example.net/things/first”,
“next”: “https://example.net/things/second”,
“create”: ”https://example.net/things”,
“delete”: “https://example.net/things/first”,
“update”: ”https://example.net/things/first”
}
}
Auf der Grundlage dieser Antwort können wir in Svelte die Teile, die für die Erstellung, Löschung oder Aktualisierung einer Ressource verantwortlich sind, wie folgt darstellen:
{#if response._links.hasOwnProperty(“create”) }.
{/if}
{#if response._links.hasOwnProperty(“delete”) }
{/if}
{#if response._links.hasOwnProperty(“update”) }
{/if}
Wie man sieht, sind die Bedingungen auf dem Frontend sehr einfach und arbeiten nur mit den vom Backend vorgegebenen Links. Das bedeutet, dass die potenziell schwerfällige Logik für die Zugriffskontrolle vollständig auf der Backend-Seite liegt, wodurch die Client-Seite stark entlastet und die Komplexität reduziert wird.
Zusammenfassung
Dieser Artikel zeigte, wie die Zugriffskontrolle zumindest visuell durch HATEOAS erreicht werden kann. Die Nichtanzeige von UI-Elementen verhindert natürlich nicht, dass ansonsten böswillige Clients auf geschützte API-Endpunkte zugreifen. Daher müssen alle Endpunkte, die einen eingeschränkten Zugriff benötigen, zusätzlich im Backend gesichert werden.