Blog
OAuth2-Gerätefluss-Proxy mit kostenlosen Azure-Komponenten

Haben Sie schon einmal REST-APIs von einem eingebetteten Gerät oder einer Konsolenanwendung aus aufgerufen? Wenn ja, haben Sie wahrscheinlich einige OAuth2-Anmeldedaten benötigt, um nachzuweisen, wer Sie sind und was Sie tun dürfen.
Diese Token ordnungsgemäß auf Ihr Gerät zu bringen, könnte mühsam sein - die Hardcodierung von Anmeldedaten in Ihrem Code ist unschön, und einen eingebetteten Webserver zu hosten, damit sich ein Benutzer anmelden kann, ist ebenfalls etwas, das Sie wahrscheinlich vermeiden möchten.
Zum Glück gibt es den Fluss Device Authorization Grant, auch bekannt als Device Flow. Er ist einer der standardisierten OAuth2-Authentifizierungsabläufe und dient dazu, Anwendungen, die selbst nur begrenzte Interaktionsmöglichkeiten haben, eine Authentifizierung zu ermöglichen.
Denken Sie zum Beispiel an eingebettete Geräte oder Konsolenanwendungen - sie können dem Benutzer nicht einfach eine Anmeldeseite präsentieren, ohne einen eingebetteten Webserver zu hosten. Diese Geräte oder Anwendungen werden in diesem Artikel device genannt, um die Rolle, die sie spielen, zu betonen.
Leider bieten nicht alle Dienste den Gerätefluss an. Um dies abzumildern, können Sie einen Proxy erstellen, der die Verwendung dieses Flusses ermöglicht, während der Proxy unter der Haube einen der gängigeren anderen Flüsse (wie den Autorisierungscode-Fluss) verwendet.
In diesem Beispiel werden wir uns darauf konzentrieren, einen solchen Proxy für die REST-API von Spotify zu erstellen. Als Herausforderung werden wir versuchen, diesen Proxy mit kostenlosen Diensten in Azure zu erstellen.
Während Spotify in der Praxis einen Gerätecodefluss für einige Partner und für seine eigenen Apple TV- und Android TV-Apps hat, unterstützt es ihn nicht für Anwendungen von Drittanbietern. Einige Hintergrundinformationen finden Sie unter Reverse Engineering von Spotifys eigener Device Authorization Grant-Implementierung.
Wie funktioniert der Gerätefluss?
Bevor wir uns mit den Einzelheiten des Hinzufügens eines Proxys befassen, lassen Sie uns den ursprünglichen Geräteablauf besprechen, der in Abbildung 1 dargestellt ist. Anstatt dem Benutzer direkt eine Anmeldeseite zu präsentieren, fordert das Gerät ein Paar von zwei Codes an (Schritt 1): einen für das Gerät und einen für den Benutzer. Das Gerät präsentiert dem Benutzer den device_code verwendet, die nach Abschluss der Autorisierung durch den Benutzer verfügbar werden.
Das Gerät kann diese Token verwenden, um API-Anfragen zu stellen (Schritt 7), wie bei jedem anderen OAuth2-Mechanismus.

Gerätefluss mit Proxy
Da Spotify diesen Fluss für benutzerdefinierte Anwendungen nicht offiziell unterstützt, ist es auch möglich, Ihren eigenen Fluss für die Erteilung der Geräteautorisierung zu implementieren, indem Sie eine zusätzliche Komponente (im Folgenden proxy genannt) zwischen Ihrem Gerät und Spotify einrichten. Der geänderte Ablauf ist in Abbildung 2 zu sehen.

- Das Gerät ruft den Autorisierungsendpunkt auf. Jetzt sollte der Proxy einen Datensatz mit den Daten
device_codeunduser_codeerstellen, sie für später in der Datenbank speichern und sie in der Antwort zurücksenden. - Der Benutzercode muss dem Benutzer angezeigt werden, zum Beispiel über ein Display oder einen Lautsprecher.
- Der Benutzer gibt die
user_codeauf der Benutzerseite ein. Der Proxy prüft dieuser_codein seiner Datenbank. Wenn dieuser_codenicht gefunden wird, wird eine Fehlermeldung angezeigt. - Wenn die
user_codegefunden wird, leitet der Proxy den Benutzer zu Spotify weiter, um sich anzumelden und die Anfrage zu genehmigen. - Nach der Anmeldung wird der Benutzer auf die Callback-Seite des Proxys umgeleitet. Die Weiterleitung enthält das Ergebnis der Aktion des Benutzers und einen Autorisierungscode.
- Der Proxy kann einen
access_tokenundrefresh_tokenvom Token-Endpunkt von Spotify abrufen, indem er den Autorisierungscode verwendet, den er im Callback erhalten hat. Der Proxy sollte die erhaltenen Berechtigungsnachweise in dem zuvor gespeicherten Datensatz nebenuser_codeunddevice_codespeichern. - Das Gerät kann den Token-Endpunkt des Proxys über
device_codenach der Verfügbarkeit der Token abfragen. Wenn das Gerät das Token erfolgreich abgerufen hat, sollte der Datensatz aus der Datenbank gelöscht werden, um Missbrauch zu verhindern. - Das Gerät kann die Ziel-API wie gewohnt mit den erhaltenen Token aufrufen.
Architektur des Gerätefluss-Proxys
Anforderungen
Der Bevollmächtigte sollte
- einen Autorisierungs-API-Endpunkt und einen Token-API-Endpunkt bereitstellen, mit denen das Gerät interagieren kann
- erstellen Sie die
device_codeunduser_codeund speichern Sie sie in einer Datenbank - eine benutzerorientierte Seite hosten, die ein kleines Formular enthält, in das der Benutzer die
user_code - die Daten abrufen und validieren
user_code - einen Callback-Endpunkt für Spotify hosten, an den der Benutzer nach der Anmeldung weitergeleitet wird. Dieser Endpunkt sollte die von Spotify gesendeten Daten verarbeiten und dem Benutzer eine Erfolgs- oder Fehlerseite anzeigen.
Zu diesem Zweck sollte der Proxy ein sehr einfaches Frontend mit einigen wenigen Backend-API-Endpunkten haben, wie in Abbildung 3 zu sehen ist.

Auswahl der Komponenten
Für unsere Herausforderung wählen wir aus den kostenlosen Diensten, die Azure anbietet.
️Hinweis: Oft sind die kostenlosen Dienste mit eingeschränkten Spezifikationen und / oder einem reduzierten SLA ausgestattet. Verwenden Sie sie nicht blindlings für Produktionszwecke. Sie können jedoch für den Zweck einer kleinen Anwendung für den persönlichen Gebrauch geeignet sein.
Es gibt zwei Varianten von kostenlosen Diensten:
- Dienste, die während des ersten Jahres Ihres Azure-Kontos kostenlos sind
- Dienste, die während der gesamten Lebensdauer Ihres Azure-Kontos kostenlos bleiben
Für unseren Device Flow Proxy benötigen wir 3 Hauptfunktionen:
- einen Ort, an dem das Frontend (Formular, in das der Benutzer den user_code eingibt) und einige Ergebnisseiten bereitgestellt werden
- einige API-Endpunkte mit Rechen- und Integrationsfunktionalitäten
- eine Datenbank/Speicher zum Speichern der aktiven Authentifizierungsdatensätze
Für diese Herausforderung werden wir diese Komponenten verwenden, die in die zweite Kategorie passen (für immer frei).
Dies beschränkt unsere Auswahl auf Static Web Apps, App Service und Azure Container Apps für die Frontend-/Backend-Fähigkeit und Cosmos DB für die Datenbank-Fähigkeit.
Frontend / Backend
Azure Static Web Apps (SWA) kann ein statisches Frontend bereitstellen und das kostenlose Tier verfügt über eine abgespeckte Version von Azure Functions namens Managed Functions, die als Backend dienen kann. Für eine einfache Webanwendung deckt dies die Bedürfnisse ab und es gibt keine Begrenzung für die Laufzeit. Für uns ist das eine gute Wahl.
SWA bietet ein kostenloses monatliches Kontingent von 100 GB Bandbreite pro Abonnement, 2 benutzerdefinierte Domains und 0,5 GB Speicherplatz pro App, was für unsere Proxy-App mehr als ausreichend ist.
Die Managed Functions sind eine "unterstützte" API in der kostenlosen Version von SWA. Es gibt noch ein paar andere Produkte, die ebenfalls als unterstützte APIs in SWA verfügbar sind, aber nicht Teil der kostenlosen Version sind - das sind Bring your own Functions, API Management, App Service und Container Apps.
Die Idee, ein unterstütztes API-Produkt in SWAs zu verwenden:
- die API und die statische Website werden über den integrierten Reverse Proxy des SWA von derselben Domain aus bedient. Dadurch entfällt die Notwendigkeit, CORS-Header (Cross-Origin Resource Sharing) zu den API-Antworten hinzuzufügen, was die Erfahrung für Entwickler weniger komplex macht.
- Das Routing erfolgt automatisch.
- Der authentifizierte Benutzerkontext aus der SWA ist für die API-Logik verfügbar.
Managed Functions deckt unseren Bedarf, aber es ist gut zu wissen, dass es nicht alle Funktionen unterstützt, die Sie vielleicht von anderen Azure Functions-Angeboten gewohnt sind. Bemerkenswerte Unterschiede sind:
- Keine anderen Funktionsauslöser als HTTP-Auslöser
- Einige bewährte Sicherheitsverfahren können nicht befolgt werden
- Derzeit keine Unterstützung für Managed Identity
- keine Unterstützung für Key Vault Referenzen
Als Alternativen zu SWA wurden folgende Möglichkeiten in Betracht gezogen:
- Azure Container Apps bietet eine lebenslange kostenlose monatliche Menge von 180.000 vCPU-Sekunden, 360.000 GiB-Sekunden und 2 Millionen Anfragen, die jedoch von einer Container-Registry abhängig ist. Azure Container Registry ist nur 12 Monate lang kostenlos verfügbar.
- App Service hat eine lebenslange kostenlose monatliche Menge von 10 Web-, Mobil- oder API-Apps mit 1 GB Speicherplatz 1 Stunde pro Tag - nicht gewählt, weil ich das serverlose Modell bevorzuge. 1 Stunde/Tag ist wahrscheinlich genug, aber es ist schwer abzuschätzen, wie sich das auswirkt.
- Der Azure Functions Consumption Plan sieht zwar kostenlos aus (1 Million > Aufrufe und 400000 GB-s), aber er setzt voraus, dass > ein Speicherkonto bereitstellt, das nicht kostenlos ist.
Datenbank/Speicherfähigkeit
Cosmos DB ist das einzige Datenbank- oder Speicherprodukt, das als kostenloser Service für immer angeboten wird. Es entspricht unseren Anforderungen, da es unsere Authentifizierungssitzungsdatensätze als JSON-Dokumente speichern kann und einfach zu handhaben ist.
Der kostenlose Tier von Cosmos DB bietet einen kostenlosen monatlichen Durchsatz von 1000 Anfrageeinheiten pro Sekunde mit 25 GB Speicherplatz, was für unsere Proxy-Anwendung mehr als ausreichend ist.
Lösung für zeitbasierte Logik
Wir möchten die Daten aus Sicherheitsgründen (siehe unten) nach einem bestimmten Zeitraum oder wenn die Daten veraltet sind, bereinigen. Das Angebot an verwalteten Funktionen in SWA unterstützt nur HTTP-getriggerte Funktionen, d.h. Funktionen, die durch einen Timer ausgelöst werden, werden nicht unterstützt.
Technisch gesehen könnte eine separate Logic App eine Option sein, aber die Verwendung der Cosmos DB-eigenen Time to Live (TTL) Funktion ist eine viel einfachere und elegantere Option.
Da wir nur eine zeitbasierte Bereinigung benötigen und keine anderen zeitgesteuerten Läufe, werden wir die native Bereinigung in Cosmos DB verwenden, indem wir eine TTL für die Datensätze setzen.
Überlegungen zur Sicherheit
Da wir hier im Wesentlichen einen benutzerdefinierten Teil der Authentifizierungskette aufbauen, ist es sehr wichtig, auf die Sicherheit zu achten.
Grundlegende Dinge wie das Nicht-Übertragen von Geheimnissen an Git, das Nicht-Hardcoding von Geheimnissen, die Verwendung von HTTPS usw. werden in diesem Artikel nicht behandelt. Der RFC enthält jedoch einige spezifische Hinweise zur Logik der Geräteautorisierung, die Sie besonders beachten sollten. Diese zusätzlichen Hinweise zielen im Wesentlichen darauf ab, Brute-Forcing und Phishing der Geheimnisse zu verhindern.
- Verwendung eines ausreichend langen Benutzercodes und Gerätecodes. Dies erhöht die Anzahl der Versuche, die zum Erraten der Codes erforderlich sind.
- Ratenbeschränkung auf Proxy-Endpunkten, um Brute-Forcing zu verhindern. Dies reduziert die Anzahl der Versuche, die ein böser Akteur durchführen kann.
- Ablauf und Bereinigung des Authentifizierungssitzungsdatensatzes aus der Datenbank nach Zeitraum X oder wenn der Datenfluss vom Gerät abgeschlossen wird (die OAuth2-Tokens werden vom Gerät empfangen). Dadurch wird sichergestellt, dass die Daten nicht länger als nötig gespeichert werden.
Reverse Engineering der Spotify-eigenen Implementierung der Geräteautorisierungserlaubnis
Bei der Lektüre des Device Authorization Grant habe ich einen Artikel gefunden, der zeigt, dass Spotify diesen Fluss für seine eigenen Apps und für Partner anbietet. Die Android TV-App ist eine davon. Ein Vorteil von Android-Apps (für uns) ist, dass sie sich relativ leicht zurückentwickeln lassen. Es ist möglich, das Anwendungspaket (.apk-Datei) herunterzuladen und es in einem Decompiler zu verarbeiten. Es gibt mehrere Online-Decompiler-Dienste, bei denen Sie die apk-Datei hochladen und die dekompilierten Java-Quelldateien und die dazugehörigen Ressourcen als Zip-Datei herunterladen können. Nachdem Sie die entpackten Dateien geöffnet haben, können Sie sie mit Visual Studio Code leicht durchsuchen. Jetzt müssen wir ein wenig raten und rätseln. Die Entwickler versuchen oft, ihren Code zu verschleiern, um uns die Suche zu erschweren, indem sie Variablennamen, Funktionsnamen usw. verdrehen. Eine Idee, dies zu umgehen, besteht darin, nach Bezeichnern oder (Teilen von) URLs zu suchen, die mit der Logik zusammenhängen, die wir untersuchen und von denen wir erwarten, dass die App sie verwendet. Der Grund dafür ist, dass die Bezeichner oder URLs selbst in der Regel nicht verfälscht werden, da sie in HTTP-Anfrage-/Antwortkörpern oder den aufzurufenden URLs verwendet werden müssen. Kandidaten für Suchbegriffe könnten aus dem RFC des Geräteflusses, aus der Spotify-eigenen Autorisierungsdokumentation (in der Erwartung, dass dieser Fluss einige gemeinsame oder ähnliche Endpunkte hat) und durch weitere Iteration dessen, was wir finden, stammen.
Beispiele für konkrete Suchbegriffe, die für uns von Interesse sind, sind:
client_idaccounts.spotify.comdevice_code
Auf diese Weise konnten wir finden
- die
client_idder App-Registrierung von Spotifys Android TV-App - dass ein Teil der Funktionen der App auf einer Website basiert, die auf https://api-partner.spotify.com/tvapp?platform=androidtv gehostet wird.
- die speziellen
scopes, die die App verwendet - die URLs und Aufrufe, die die App macht, um Token zu erhalten.
Ich habe die Ergebnisse in einem Thema im Spotify Developer Forum vorgestellt.
Fazit
In diesem Artikel haben wir den OAuth2 Device Flow besprochen und uns angesehen, wie wir einen Proxy für Dienste erstellen können, die diesen Authentifizierungsfluss nicht anbieten. Wir haben die Anforderungen an einen solchen Proxy erörtert und uns angesehen, welche kostenlosen Komponenten Azure anbietet, um diese Anforderungen zu erfüllen. Wir haben die Sicherheitsaspekte besprochen und wie man damit umgeht. Schließlich haben wir uns angeschaut, wie man den Device Flow, den Spotify hat, aber derzeit nicht für Nicht-Partner-Entwickler anbietet, zurückentwickeln kann.
Referenz
Andere relevante Artikel:
- Alle gewinnen mit dem Device Flow
- Verwendung des OAuth 2.0-Geräteflusses zur Authentifizierung von Benutzern in Desktop-Anwendungen
- Authentifizierung in der Smart TV App - Gerätecodefluss
- Illustrierter Gerätefluss (RFC 8628)
Andere Implementierungen:
- Spotify Player für alte Macs
- MacAuth (basierend auf ASP.Net Core)
- Fügen Sie den OAuth 2.0 Gerätefluss zu einem beliebigen OAuth Server (PHP-basiert) hinzu.

Verfasst von
Hans Bakker
Contact