Vuejs 3 Applikation und Flask-API mit MSAL verbunden
Ausgangspunkt
Meine Heizung hatte vor einiger Zeit mehrfach Ausfälle. Das hat sich dahingehend geäußert, dass die Heizung nachts immer heißer wurde, der Sicherheitsschalter für die Übertemperatur ausgelöst hat und morgens das Wasser beim Duschen kalt war, da dieses aufgrund der nächtlichen Abschaltung nicht mehr aufheizt wurde.
Ich habe dann im DIY-Stil einen Fühler eingebaut, der in Verbindung mit NodeMCU, Raspberry-PI, Django-App, etc. die aktuelle Temperatur in eine MySQL-Datenbank speichert. An diese Messwerte ist ein Telegram-Bot angebunden, der zwei Grenzwerte (zu niedrig oder zu hoch) direkt auf’s Smartphone meldet. Das ist aber eine andere Geschichte …
Intern (zuhause) hatte ich schon eine Django-App laufen, die mir den zeitlichen Temperaturverlauf - die Temperatur wird alle 10 Minuten gemessen - in einem Liniendiagramm visualisiert. Das wollte ich auf einen anderen Technologiestack heben und von außerhalb meines zu Hauses veröffentlichen. Da es nun aber öffentlich erreichbar sein sollte, musste ein Authentifizierung her. Soviel zum Ausgangspunkt.
Technologiestack
Beruflich entwickle ich meine Frontends seit geraumer Zeit mit VUEjs. Das wollte ich in diesem Fall ebenso handhaben. Diese Webseite und die Webseite meiner Band werden bereits auf Netlify gehostet, weshalb das Projekt ebenfalls auf Netlify laufen soll. Zum einen, weil es geht und sich gleichzeitig sehr bequen per CI/CD an Github anbinden lässt.
Die MySQL-Datenbank lief bereits extern auf meinem gemieteten Linux-Server bei Contabo. Diesen wollte ich deshalb auch für die Backend-API nutzen. Ich mag für solche Zwecke die Programmiersprache Python, da sie für alle denkbaren Probleme ein Modul bereitstellt und mit “venv” die Möglichkeit bietet, verschiedenee Umgebungen zu nutzen, ohne dass man sich durch zu viele Module das gesamte System zerschießt. Am Ende habe ich mich für die Umsetzung mit Flask entschieden.
Flask ist ein leichtgewichtiges Web-Framework für Python. Als sogenanntes Micro-Framework schreibt es keine bestimmten Tools vor, bietet aber trotzdem alle grundlegenden Funktionen, die für den Aufbau von webanwendungen erforderlich sind. Somit sollte die API, die die HTTP-Anfragen entgegennimmt, Daten aus der Datenbank holt und diese Daten zurückgibt, mit Flask umgesetzt werden.
Bei der Wahl des Authentifizierunganbieters wollte ich die Applikation auf Frontend- und Backendseite mit Azure Entra ID, also mit der Microsoft Authentication Library umsetzen. Diese gibt es für VUEjs und Flask, so dass es daran ging, Frontend und Backend entsprechend abzusichern.
Anforderungen bzw. Herausforderungen
Die Anforderungen oder vielmehr die Herausforderungen sind nachfolgend aufgelistet.
- Die Backend-API darf sich nicht “anonym” aufrufen lassen.
- Das Frontend darf bestimmte Daten nicht als “anonymer” Benutzer anzeigen.
- Die Benutzer, die die Anwendung nutzen dürfen, werden über Azure Entra ID verwaltet.
- Frontend und Backend sollen so zusammenarbeiten, dass man sich am Frontend einloggt und anschließend gleichzeitig auch die Berechtigung für die Backend-API hat.
Konfiguration der Komponenten
Azure App Registration für “Backend”
- Neue App Registrierung in Azure anlegen
- Menüpunkt “API permissions”: Hier werden die Berechtigungen gesteuert, dass sich das Frontend per Token beim Backend melden darf:
Read.All
… delegated und freigeben. - Menüpunkt “Expose an API”:
Scope Read.All
… diese URL ist wichtig für das Backend!!! - Menüpunkt “App roles”: Hier kann man nochmal explizite Rechte ergänzen, die man dann zugewiesenen Benutzern geben kann, z. B.
Write.All
Azure App Registration für “Frontend”
- Neue App Registrierung in Azure anlegen
- Menüpunkt “Authentication”: Hier wird der eigentliche Login-Prozess gesteuert: SPA Redirect-URIs einrichten, Haken gesetzt für
Access tokens (used for implicit flows)
undID tokens (used for implicit and hybrid flows)
- Menüpunkt “API permissions”: Hier werden die Berechtigungen konfiguriert, die von diese App zur Verfügung gestellt werden können: Microsoft Graph (email, Mail.Read, … ) und (wichtig)
Read.All
des Backends - vorher konfiguriert unter “API Permissions” des Backends. - Menüpunkt “App roles”: Hier kann man nochmal explizite Rechte ergänzen, die man dann zugewiesenen Benutzern geben kann. Brauchen wir aktuell nicht.
Azure Enterprise Application für “Backewnd” oder “Frontend”
- Benutzer zuweisen: Hier werden die User verwaltet “Users and groups” und Benutzer entsprechende Rollen, die bei den App-Registrations erstellt wurden, zugewiesen werden.
VUEjs
- Verwendet das Modul
@msal-browser
- MSAL wird konfiguriert. Dazu benötigt man die Tenant-ID und die ID der App Registration. Außerdem Redirct-URL und Logout-URL → muss mit dern SPA Redirect-URIs der Frontend-App übereinstimmen!
- Wichtig: Das Access-Token für den Zugriff auf die Frontend-App muss zuerst abgerufen werden. Das Zugriffstoken für die API verwendet dann die URL, die bei der API über “Expose an API” bereitgestellt wurde. Das Token muss separat geholt werden!
Flask
- Verwendet
flask_azure_oauth
- MSAL muss auch konfiguriert werden: Tenant-ID und IP der “Backend” App Registration wird benötigt.
- Das eigentliche “Absichern” der Apps ist dann recht einfach:
@auth()
bzw.@auth("Write.All")
oder welches “APP Role” auch immer definiert wurde und hier geprüft werden soll.
Fazit
In diesem Beispiel habe ich Entra ID für die Authentifizierung benutzt, ohne dass die eigentlichen Anwendungen bei Azure gehostet werden. Die Services Frontend und Backend sind getrennt und es lassen sich explizite Rechte für den Zugriff vergeben, die der Sicherheit der Anwendung zugute kommen.
Zurück