Freigeben über


Tutorial: Hinzufügen der Anmeldung zu einer Python Flask-Web-App

Dieses Tutorial ist der dritte Teil einer Tutorialreihe, in der das Erstellen einer Python Flask-Web-App von Grund auf und das Integrieren der Authentifizierung mithilfe von Microsoft Identity Platform veranschaulicht werden. In diesem Tutorial fügen Sie Code zur Authentifizierung von Benutzern in der von Ihnen erstellten App hinzu.

  • Importieren der erforderlichen Module und der Konfiguration
  • Erstellen einer Instanz einer Flask-Web-App
  • Konfigurieren der ProxyFix-Middleware für die lokale Entwicklung
  • Hinzufügen von Code zum Anmelden und Abmelden von Benutzern
  • Definieren eines Einstiegspunkts für die Web-App

Importieren erforderlicher Pakete und Konfigurationen

Die von Ihnen erstellte Web-App verwendet das auf MSAL Python basierende Paket identity.web, um Benutzer in Web-Apps zu authentifizieren. Fügen Sie zum Importieren des identity.web-Pakets, des Flask-Frameworks, der Flask-Module, der Flask-Sitzung und der App-Konfigurationen, die im vorherigen Tutorial definiert wurden den folgenden Code zu app.py hinzu:

import identity.web
import requests
from flask import Flask, redirect, render_template, request, session, url_for
from flask_session import Session

import app_config

In diesem Codeschnipsel importieren Sie die Funktionen und Objekte redirect, render_template, request, session und url_for für die Verarbeitung von Webanforderungen und Sitzungen in Flask. Darüber hinaus importieren Sie das app_config-Element, das Konfigurationseinstellungen für Ihre App enthält.

Erstellen einer Instanz der Flask-Web-App

Nach dem Importieren der erforderlichen Module initialisieren wir die Web-App mithilfe der Konfigurationen in app-config. Fügen Sie zum Erstellen einer Instanz Ihrer Web-App den folgenden Codeschnipsel zu app.py hinzu:

app = Flask(__name__)
app.config.from_object(app_config)
assert app.config["REDIRECT_PATH"] != "/", "REDIRECT_PATH must not be /"
Session(app)

Im obigen Codeschnipsel initialisieren Sie eine neue Flask-Anwendung und laden die Konfigurationseinstellungen mithilfe von app.config.from_object(app_config). Mit from_object erbt die App die Konfigurationen von dem in (app_config) angegebenen Objekt.

Außerdem führen Sie eine Assertionsüberprüfung durch, um sicherzustellen, dass der Umleitungspfad Ihrer App nicht auf den Stammpfad („/“) festgelegt ist. Session(app) initialisiert die Sitzungsverwaltung für Ihre App, mit der Sie Sitzungen verarbeiten und Daten wie Benutzerauthentifizierungsstatus über mehrere Anforderungen hinweg speichern können.

Konfigurieren der ProxyFix-Middleware für die lokale Entwicklung

Da die Beispielweb-App auf dem lokalen Host ausgeführt wird, verwenden wir die ProxyFix-Middleware, um das URL-Schema und die Hostinformationen in den Anforderungsheadern zu korrigieren. Fügen Sie app.py den folgenden Code hinzu, um ProxyFix anzuwenden:

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)

Initialisieren eines Authentifizierungsobjekts

Als Nächstes initialisieren Sie ein Authentifizierungsobjekt, indem Sie eine Instanz der [identity.web.Auth](https://identity-library.readthedocs.io/en/latest/#identity.web.Auth)-Klasse erstellen. Sie übergeben außerdem beim Initialisieren des Authentifizierungsobjekts wie folgt die Parameter session, authority, client_id und client_credential im Konstruktor:

app.jinja_env.globals.update(Auth=identity.web.Auth)  # Useful in template for B2C
auth = identity.web.Auth(
    session=session,
    authority=app.config["AUTHORITY"],
    client_id=app.config["CLIENT_ID"],
    client_credential=app.config["CLIENT_SECRET"],
)

In diesem Codeschnipsel fügt app.jinja_env.globals.update(Auth=identity.web.Auth) eine neue globale Variable mit dem Namen Auth hinzu und weist ihr den Wert identity.web.Auth zu. Dadurch wird Auth in allen Vorlagen zugänglich, die von der Flask-Anwendung gerendert werden.

Anmelden von Benutzern

Der Autorisierungsflow, den Sie in dieser App erstellen, besteht aus zwei Teilen. Im ersten Teil rufen Sie die auth.log_in-Funktion zum Anmelden von Benutzern auf, wie hier gezeigt:

@app.route("/login")
def login():
    return render_template("login.html", version=__version__, **auth.log_in(
        scopes=app_config.SCOPE, # Have user consent to scopes during log-in
        redirect_uri=url_for("auth_response", _external=True), # Optional. If present, this absolute URL must match your app's redirect_uri registered in Microsoft Entra admin center
        prompt="select_account",  # Optional.
        ))

Wenn ein Benutzer zur /login-URL in Ihrer App navigiert, ruft Flask die Ansichtsfunktion auf, die die Anforderung zum Rendern der login.html-Vorlage verarbeitet. Rufen Sie innerhalb von login() die auth.log_in-Funktion mit einer Liste von Bereichen auf, denen der Benutzer während des Anmeldevorgangs zustimmen sollte. Außerdem stellen Sie das redirect_uri-Element in den Parametern bereit. Dieses Element sollte mit dem Umleitungs-URI der App im Microsoft Azure Admin Center übereinstimmen.

Sie können optional Parameter wie prompt hinzufügen. Dieser Parameter steuert das Verhalten der Anmeldeaufforderung, indem die erneute Authentifizierung, die Benutzereinwilligung oder die Auswahl zwischen Konten mit aktiven Sitzungen angefordert wird.

Im zweiten Teil des Autorisierungsflows behandeln Sie die Authentifizierungsantwort, indem Sie die auth.complete_log_in-Funktion innerhalb des redirect_uri-Controllers aufrufen, wie hier gezeigt:

@app.route(app_config.REDIRECT_PATH)
def auth_response():
    result = auth.complete_log_in(request.args)
    if "error" in result:
        return render_template("auth_error.html", result=result)
    return redirect(url_for("index"))

Die complete_log_in()-Funktion übernimmt das eingehende auth_response-Wörterbuch als Abfrageparameter. Bei erfolgreicher Ausführung leitet die Funktion den Benutzer mithilfe von redirect(url_for("index")) an die Route „Index“ um. Das bedeutet, dass sich der Benutzer erfolgreich angemeldet hat. Seine Informationen sind als Wörterbuch verfügbar, das Ansprüche aus einem bereits überprüften ID-Token enthält.

Wenn das Ergebnis gemäß der Bedingung if "error" in result: einen Fehler enthält, wird dem Benutzer die Vorlage "auth_error.html" angezeigt.

Abmelden von Benutzern

Um Benutzer von Ihrer Flask-Anwendung abzumelden, rufen Sie die auth.log_out()-Methode wie folgt auf:

@app.route("/logout")
def logout():
    return redirect(auth.log_out(url_for("index", _external=True)))

Wenn ein Benutzer zur /logout-URL-Route in der App navigiert, ruft Flask die Abmeldefunktion auf, mit der der Benutzer von der aktuellen App abgemeldet wird. Sie geben zudem die Seite an, zu der Benutzer bei der Abmeldung umgeleitet werden sollen. Im Codeschnipsel leiten wir Benutzer mithilfe von url_for("index", _external=True). zur Startseite der App um.

Definieren eines Einstiegspunkts für die Web-App

Fügen Sie nach der Implementierung der Anmelde- und Abmeldelogik einen Einstiegspunkt zur Startseite Ihrer App hinzu, indem Sie die index()-Funktion wie folgt erstellen:

@app.route("/")
def index():
    if not (app.config["CLIENT_ID"] and app.config["CLIENT_SECRET"]):
        # This check is not strictly necessary.
        # You can remove this check from your production code.
        return render_template('config_error.html')
    if not auth.get_user():
        return redirect(url_for("login"))
    return render_template('index.html', user=auth.get_user(), version=__version__)

Die index()-Funktion wird aufgerufen, wenn ein Benutzer zur Stamm-URL der App („/“) navigiert. Sie verarbeitet Konfigurationsüberprüfungen und überprüft die Benutzerauthentifizierung, bevor die Startseite der App gerendert wird. Sie überprüft, ob die Client-ID und der geheime Clientschlüssel in der Konfiguration fehlen. Wenn einer der Werte fehlt oder beide Werte fehlen, wird die "config_error.html"-Vorlage in Flask gerendert.

Die Funktion ruft außerdem auth.get_user() auf, um zu überprüfen, ob der Benutzer authentifiziert ist oder nicht. Wenn der Benutzer nicht authentifiziert ist, leitet er ihn an die "login"-Route weiter. Ist er authentifiziert, rendert Flask die Vorlage „index.html“ und übergibt das Benutzerobjekt (abgerufen aus auth.get_user()) zum Rendern.

Nächste Schritte