Erstellen Sie eine Flaschenanwendung mit Google Login

Erstellen Sie eine Flaschenanwendung mit Google Login

Sie haben wahrscheinlich die Option fürGoogle Login auf verschiedenen Websites gesehen. Einige Websites bieten auch mehr Optionen wieFacebook Login oderGitHub Login. Mit all diesen Optionen können Benutzer vorhandene Konten verwenden, um einen neuen Dienst zu verwenden.

In diesem Artikel arbeiten Sie an der Erstellung einer Webanwendung fürFlask. Mit Ihrer Anwendung kann sich ein Nutzer mit seiner Google-Identität anmelden, anstatt ein neues Konto zu erstellen. Diese Methode der Benutzerverwaltung bietet unzählige Vorteile. Dies ist sicherer und einfacher als die Verwaltung der herkömmlichen Kombinationen aus Benutzername und Passwort.

Dieser Artikel ist einfacher, wenn Sie diebasics of Python bereits verstehen. Es wäre auch hilfreich, etwas über Web-Frameworks und HTTP-Anforderungen zu wissen, aber das ist nicht unbedingt erforderlich.

Am Ende dieses Artikels können Sie:

  • Erstellen Sie eine Flask-Webanwendung, mit der sich Benutzer bei Google anmelden können

  • Erstellen Sie Client-Anmeldeinformationen für die Interaktion mit Google

  • Verwenden Sie Flask-Login für die Verwaltung von Benutzersitzungen in einer Flask-Anwendung

  • Besseres Verständnis von OAuth 2 und OpenID Connect (OIDC)

Sie können auf das Feld unten klicken, um den Code für die Anwendung zu erhalten, die Sie in diesem Artikel erstellen:

Warum Google Login für Ihre Nutzer verwenden?

Möglicherweise möchten Sie, dass einzelne Benutzer Profile haben. Oder Sie möchten Funktionen nur bestimmten Benutzern bereitstellen. In jedem Fall müssen Sie wissen, wer mit Ihrer Anwendung interagiert. Mit anderen Worten, Sie müssen Benutzer authentifizieren und auf eindeutige Weise identifizieren.

Die traditionelle Lösung besteht darin, einen eindeutigen Benutzernamen und ein geheimes Passwort zu verwenden. Ihre Anwendung würde diese Informationen speichern und bei Bedarf danach fragen. Diese Lösung hat jedoch einige Nachteile:

  • Sie müssen die Passwörter sicher verwalten.

  • Sie müssen alle kontobezogenen Funktionen implementieren:

    • Zwei-Faktor-Authentifizierung

    • Passwort zurücksetzen

  • Sie müssen sich vor böswilligen Anmeldeversuchen schützen.

  • Ihre Benutzer müssen sich noch einen Benutzernamen und ein Passwort merken.

Durch die Verwendung des Google-Logins für Ihre Nutzer übertragen Sie diese Verantwortung auf sie. Ihre Anwendung wartet darauf, dass der Benutzer die Authentifizierung durchläuft. Google informiert Ihre Anwendung dann über diesen Nutzer. Zu diesem Zeitpunkt können Sie sie effektiv in Ihrer Anwendung anmelden.

Sie müssen keine Passwörter speichern, und Google kümmert sich um die gesamte Sicherheit.

Wie Anwendungen Google Login verwenden

Es gibt zwei sehr beliebte und wichtige Spezifikationen, die alsOAuth 2 undOpenID Connect (OIDC) bezeichnet werden. OIDC basiert auf OAuth 2 und fügt einige neue Ideen und Konzepte hinzu.

Diese Spezifikationen definieren, wie eine Drittanbieteranwendung Informationen von einem anderen Dienst erhalten kann. Dies beinhaltet normalerweise das Einholen der Zustimmung eines Benutzers. Um dies ein wenig zu entpacken, schauen wir uns an, wie dies für die Anwendung gilt, die Sie erstellen möchten.

Sie schreiben gerade eine Drittanbieteranwendung, mit der sich ein Benutzer mit der SchaltflächeGoogle Loginanmelden kann. Dazu muss Google über Ihre Anwendung Bescheid wissen. Glücklicherweise können Sie Ihre Bewerbung als Kunde bei Google registrieren.

Sobald ein Nutzer zu Ihrer Anwendung kommt und die TasteGoogle Login drückt, können Sie ihn an Google senden. Von dort aus muss Google sicherstellen, dass der Nutzer zustimmt, seine E-Mail-Adresse und andere Informationen an Ihre Anwendung weiterzuleiten. Sollte der Nutzer zustimmen, sendet Google einige Informationen an Ihre Anwendung zurück. Sie speichern diese Informationen dann und können später darauf verweisen, um den Benutzer effektiv anzumelden.

OpenID Connect Details

Um Informationen im Namen eines Benutzers anzufordern, müssen Sie einclient für den Authentifizierungsserver werden, der auch als Anbieter bezeichnet wird. Das erste, was Sie feststellen werden, wenn Sie sich mit diesen Spezifikationen befassen, ist, dass es viele überlappende Begriffe und Konzepte gibt.

Als Drittanbieteranwendung (auch als Client bezeichnet) möchten Sie im Namen des Benutzers Informationen vom Anbieter erhalten. Es gibt eine Reihe von Schritten, die dies ermöglichen, und diese Schritte müssen in einer bestimmten Reihenfolge ausgeführt werden. Aus diesem Grund hören Sie manchmal OAuth 2 und OpenID Connect, die alshandshake,flow oderdance bezeichnet werden.

Diese Schritte sind im Großen und Ganzen:

  1. Sie registrieren eine Drittanbieteranwendung als Client beim Anbieter:

    • Sie erhalten eindeutige Client-Anmeldeinformationen vom Anbieter.

    • Sie werden diese Client-Anmeldeinformationen verwenden, um sich später beim Anbieter zu authentifizieren (zu beweisen, wer Sie sind).

  2. Der Client sendet eine Anfrage an dieauthorization-URL des Anbieters

  3. Der Anbieter fordert den Benutzer auf, sich zu authentifizieren (zu beweisen, wer er ist).

  4. Der Anbieter bittet den Benutzer, dem in seinem Namen handelnden Kunden zuzustimmen:

    • Normalerweise beinhaltet dies einen eingeschränkten Zugriff und es wird dem Benutzer klar gemacht, wonach der Client fragt.

    • Dies ist wie wenn Sie eine App auf Ihrem Telefon genehmigen müssen, um Zugriff auf Standort oder Kontakte zu erhalten.

  5. Der Anbieter sendet dem Client einen eindeutigen Autorisierungscode.

  6. Der Client sendet den Autorisierungscode an dietoken-URL des Anbieters zurück.

  7. Der Anbieter sendet die Client-Token zur Verwendung mit anderen Anbieter-URLs im Namen des Benutzers.

Note: Die obigen Schritte gelten für den Autorisierungscode-Fluss gemäß OAuth 2.

Diese Schritte umfassen beide bisher genannten Standards. OpenID Connect (OIDC) basiert auf OAuth 2 und fügt einige zusätzliche Funktionen und Anforderungen hinzu, die hauptsächlich den Authentifizierungsprozess betreffen. Abgesehen von der im obigen Ablauf erwähnten Authentifizierung sind die wichtigen OIDC-Konzepte für Ihre Anwendungprovider configuration unduserinfo endpoint.

Dieprovider configuration enthalten Informationen zum Anbieter, einschließlich der genauen URLs, die Sie für den OAuth 2-Flow verwenden müssen. Bei einem OIDC-Anbieter gibt es eine Standard-URL, mit der Sie ein Dokument mitstandardized fields zurückerhalten können.

Dieuserinfo endpoint geben Informationen über den Benutzer zurück, nachdem Sie den OAuth 2-Fluss durchlaufen haben. Dazu gehören die E-Mail-Adresse und einige grundlegende Profilinformationen, die Sie in Ihrer Anwendung verwenden. Um diese Benutzerinformationen zu erhalten, benötigen Sie ein Token vom Anbieter, wie im letzten Schritt des obigen Ablaufs beschrieben.

Sie sehen die Details darüber, wie die Anbieterkonfiguration und der Benutzerinformationsendpunkt später verwendet werden können.

Erstellen eines Google-Clients

Der erste Schritt zum Aktivieren der OptionGoogle Loginbesteht darin, Ihre Anwendung als Client bei Google zu registrieren. Gehen wir dazu die Schritte durch.

Beachten Sie zunächst, dass Sie ein Google-Konto benötigen. Sie haben bereits eine, wenn Sie Google Mail verwenden.

Als nächstes gehen Sie zuGoogle developers credentials page.

Sobald Sie angemeldet sind, werden Sie möglicherweise aufgefordert, den Nutzungsbedingungen zuzustimmen. Wenn Sie diesen zustimmen, drücken Sie auf der nächsten Seite die TasteCreate credentials. Wählen Sie die Option fürOAuth client ID:

Google create credentials screen shot

Wählen Sie oben die OptionWeb application. Sie können dem Client auch im FeldNameeinen Namen geben. Der von Ihnen angegebene Name wird den Benutzern angezeigt, wenn sie Ihrer in ihrem Namen handelnden Anwendung zustimmen.

Sie führen Ihre Webanwendung vorerst lokal aus, sodass SieAuthorized JavaScript origins aufhttps://127.0.0.1:5000 undAuthorized redirect URIs aufhttps://127.0.0.1:5000/login/callback setzen können. Auf diese Weise kann Ihre lokale Flask-Anwendung mit Google kommunizieren.

Drücken Sie abschließendCreate und notieren Sie sich dieclient ID undclient secret. Beides benötigen Sie später.

Erstellen Sie Ihre eigene Webanwendung

Nun zum lustigen Teil, in dem Sie das erlernte Wissen anwenden, um eine tatsächliche Webanwendung zu erstellen!

Beginnen wir mit dem Ziel. Sie möchten eine Anwendung erstellen, mit der sich Benutzer mit ihrem Google-Konto anmelden können. Diese Anwendung sollte in der Lage sein, einige grundlegende Informationen über den Nutzer von Google abzurufen, z. B. dessen E-Mail-Adresse. Dann sollte die Anwendung grundlegende Benutzerinformationen in einer Datenbank speichern.

Schauen wir uns zunächst das Framework und die Bibliotheken an, die Sie verwenden werden.

Flasche

Flask ist ein leichtes Web-Framework, ein selbsternanntesmicroframework. Es enthält integrierte Tools für die grundlegenden Aufgaben, die eine Webanwendung ausführen wird, z. B. das Weiterleiten von URLs und das Verarbeiten von HTTP-Anforderungen.

Ich habe mich für Flask als Beispiel für seine Beliebtheit und Einfachheit entschieden. Die Dinge, die Sie über OAuth 2 und OIDC gelernt haben, sind jedoch nicht spezifisch für Flask. Selbst die Bibliothek, mit der Sie OAuth 2 und OIDC vereinfachen, kann in jedem Python-Code verwendet werden. Mit anderen Worten, mit einigen geringfügigen Änderungen können Sie das, was Sie hier lernen, auf ein anderes Framework Ihrer Wahl anwenden.

Flask-Login

Ein weiteres Tool, mit dem Sie den Umgang mit Benutzern vereinfachen können, istflask_login, dasuser session management bereitstellt.

Diese Bibliothek erledigt einige Dinge hinter den Kulissen und bietet Ihnen einige Tools, die den Benutzern helfen. Es bietet nämlich Dienstprogramme, mit denen Sie wissen, wann ein Benutzer angemeldet und abgemeldet ist. Dazu wird eine Benutzersitzung in einem Browser-Cookie verwaltet.

Es übernimmt auch das An- und Abmelden von Benutzern, einschließlich der Erstellung von Datenbankeinträgen für diese Benutzer. Unter dem Aspekt Ihres Codes macht es jedoch wirklich alles viel einfacher (was Sie bald sehen werden).

OAuthLib

Es gibt einen allgemeinen Satz, der für sicherheitsrelevanten und standardkonformen Code sehr zutreffend ist: "Das Rad nicht neu erfinden."

OAuth 2- und OpenID Connect-Standards sind kompliziert. Werfen Sie einen Blick auf den RFC und die Spezifikationen, und Sie werden sehen. Sie sind dicht. Ein Fehler bedeutet, dass Sie möglicherweise eine Sicherheitslücke in Ihrer Anwendung öffnen.

Sie werden also keinen Code schreiben, um diese Standards zu implementieren. Sie werden ein Python-Paket verwenden, das nach bestimmten Kriterien ausgewählt wurde:

  1. Es ist eine beliebte und allgemein empfohlene Bibliothek. Viele andere Pakete verwenden diese Bibliothek intern.

  2. Es ist sehr aktiv, und die Leute reparieren häufig Fehler.

  3. Es ist kampferprobt und gibt es seit 2012.

Es gibt Web-Framework-spezifische Pakete, die diese Bibliothek verwenden, um sie enger in Flask, Django, Pyramid und andere zu integrieren. Um den Code, den Sie hier lernen, Framework-unabhängig zu halten, verwenden Sie diese Bibliothek jedoch direkt ohne ausgefallene Wrapper.

Abhängigkeiten installieren

Es gibt eine Reihe von Abhängigkeiten von Drittanbietern, mit denen Sie Ihr Leben einfacher gestalten können. Hier ist eine Zusammenfassung dieser Abhängigkeiten:

  • Ein Webframework zur Vereinfachung typischer Webanwendungsaufgaben (Flask)

  • Eine kopfschmerzfreie Methode zum Verwalten von Benutzersitzungen (Flask-Login)

  • Eine kampferprobte OIDC-Bibliothek (oauthlib)

Darüber hinaus verwenden Sie Folgendes:

  • Eine Datenbank zum Speichern einiger Informationen über Benutzer, die sich anmelden (SQLite)

  • Eine benutzerfreundliche Möglichkeit, HTTP-Anfragen an Google zu senden (requests)

  • Eine schnelle Möglichkeit, die sichere Ausführung mithttps lokal zu aktivieren (pyOpenSSL)

SQLite ist Teil der Standard-Python-Bibliothek, die anderen Pakete jedoch nicht. Sie müssen also einige Abhängigkeiten installieren. Lassen Sie uns zunächst Schritt für Schritt die Erstellung dieser Anwendung durchgehen.

Zunächst müssen Sie die oben genannten Abhängigkeiten von Drittanbietern installieren. Dazu erstellen Sie einerequirements.txt-Datei mit folgendem Inhalt:

requests==2.21.0
Flask==1.0.2
oauthlib==3.0.1
pyOpenSSL==19.0.0
Flask-Login==0.4.1

Note: Andere Versionen der Pakete funktionieren möglicherweise, dies sind jedoch Versionen, die beim Schreiben und Testen dieses Artikels verwendet wurden.

Als Nächstes können Sie diese Abhängigkeiten mitpip, dem Paketinstallationsprogramm von Python, installieren.

Note: Es wird allgemein empfohlen, virtuelle Umgebungen zu verwenden, wenn Sie Abhängigkeiten für verschiedene Python-Anwendungen auf Ihrem Computer installieren möchten. Weitere Informationen finden Sie unterPython Virtual Environments: A Primer.

Führen Sie zum Installieren aus der Dateirequirements.txtden folgenden Befehl in Ihrem Terminal aus:

$ pip install -r requirements.txt

Jetzt kannst du rocken und rollen! Lassen Sie uns direkt in den Code eintauchen.

Importe, Konfiguration und Einrichtung

Fügen Sie zunächst einige Dateien hinzu, um einige grundlegende Datenbankfunktionen und die Benutzerverwaltung zu unterstützen. Diese werden nicht abschnittsweise beschrieben, hauptsächlich weil das Eintauchen in die Implementierungsdetails vonPython databaseein Kaninchenbau ist, der uns von unserem Ziel ablenken würde.

Dieschema.sql-Datei ist nur eine SQL-Datei, die eine Benutzertabelle in unserer Datenbank erstellt. In dieser Datei sehen Sie die Felder, die Sie pro Benutzer speichern werden.

Diese nächste Datei enthält die KlasseUser, in der Informationen gespeichert und aus der Datenbank abgerufen werden. Der Name, die E-Mail-Adresse und das Profilbild werden alle von Google abgerufen, was Sie später im Artikel sehen werden.

Nachdem Sie die Dateiendb.py,schema.sql unduser.py aus dem obigen Code erstellt haben, können Sie eine neue Dateiapp.py erstellen. Fügen Sie die folgenden Importe hinzu:

# Python standard libraries
import json
import os
import sqlite3

# Third-party libraries
from flask import Flask, redirect, request, url_for
from flask_login import (
    LoginManager,
    current_user,
    login_required,
    login_user,
    logout_user,
)
from oauthlib.oauth2 import WebApplicationClient
import requests

# Internal imports
from db import init_db_command
from user import User

Sie werden all diese später verwenden, daher ist es im Moment nicht so wichtig, sie alle zu verstehen. Der nächste Teil in Ihrenapp.py ist eine Konfiguration:

# Configuration
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", None)
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", None)
GOOGLE_DISCOVERY_URL = (
    "https://accounts.google.com/.well-known/openid-configuration"
)

So speichern Sie die Google Client-ID und das Client-Geheimnis, die Sie zuvor in diesem Artikel erstellt haben sollten. Diese werden später im OIDC-Flow verwendet.

Ihre Anwendung versucht, die Client-Anmeldeinformationen durch Lesen von Umgebungsvariablen abzurufen. Dafür gibt es einige Gründe:

  1. Sie müssen Ihren Code später nicht ändern, wenn Sie andere Anmeldeinformationen verwenden möchten. Sie müssen lediglich die Umgebung aktualisieren.

  2. Sie können Ihre geheimen Anmeldeinformationen nicht versehentlich an GitHub (oder ein anderes öffentliches Repository) übergeben.

Viele Leute legen versehentlich Geheimnisse in öffentlichen Repositories fest, was ein ziemlich ernstes Sicherheitsrisiko darstellt. Es ist besser, sich durch die Verwendung von Umgebungsvariablen davor zu schützen.

Tip: Mitexport GOOGLE_CLIENT_ID=your_client_id können Sie Ihre Client-Anmeldeinformationen als Umgebungsvariablen im Linux-Bash-Terminal und im Mac OS X-Terminal festlegen (ähnlich fürGOOGLE_CLIENT_SECRET).

Wenn Sie unter Windows arbeiten, können Sieset GOOGLE_CLIENT_ID=your_client_id in der Eingabeaufforderung verwenden.

Alternativ können Sie die Zeichenfolgencoulddirekt hier einfügen und in diesen Variablen speichern. However, das Client-Geheimnis solltenot freigegeben oder in einem öffentlichen Repository festgeschrieben werden. Mit anderen Worten, achten Sie darauf, diese Datei nicht einzuchecken, wenn Sie hier Ihre echten Client-Anmeldeinformationen einfügen.

Im Folgenden finden Sie einen Code mit globalen Variablen und eine naive Datenbankinitialisierungslogik. Abgesehen von der Datenbankinitialisierung ist das meiste davon die Standardmethode zum Einrichten von Flask, Flask-Login und OAuthLib, über die Sie zuvor gelesen haben:

# Flask app setup
app = Flask(__name__)
app.secret_key = os.environ.get("SECRET_KEY") or os.urandom(24)

# User session management setup
# https://flask-login.readthedocs.io/en/latest
login_manager = LoginManager()
login_manager.init_app(app)

# Naive database setup
try:
    init_db_command()
except sqlite3.OperationalError:
    # Assume it's already been created
    pass

# OAuth 2 client setup
client = WebApplicationClient(GOOGLE_CLIENT_ID)

# Flask-Login helper to retrieve a user from our db
@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)

Beachten Sie, dass Sie bereits die Client-ID von Google verwenden, um den Client vonoauthlibinWebApplicationClientzu initialisieren.

Sie können eine andere UmgebungsvariableSECRET_KEY alsFlask and Flask-Login will use erstellen, um Cookies und andere Elemente kryptografisch zu signieren.

Webanwendungsendpunkte

Nun zu den lustigen Sachen. Sie werden vier Endpunkte für Ihre Webanwendung schreiben:

  1. Eine für die Homepage

  2. Eine zum Starten des Benutzeranmeldevorgangs

  3. Eine für einen Rückruf, zu dem Google weiterleitet, nachdem sich ein Nutzer angemeldet hat

  4. Eine zum Abmelden

Diese Endpunkte werden durch verschiedene URLs in Ihrer Anwendung mit sehr kreativen Namen definiert:

  1. Startseite: /

  2. Einloggen: /login

  3. Login-Rückruf: /login/callback

  4. Ausloggen: /logout

Natürlich möchten Sie später möglicherweise zusätzliche Seiten und Funktionen hinzufügen. Das Endergebnis dieser Anwendung ist vollständig erweiterbar, um alles hinzuzufügen, was Sie möchten.

Sie fügen den folgenden Code für diese Endpunkte in die Dateiapp.pyein. Schauen wir uns den Code jedes dieser Endpunkte einzeln an.

Startseite

Dies ist visuell nichts Besonderes, aber Sie fügen eine übersichtliche Logik hinzu, um etwas anderes anzuzeigen, wenn ein Benutzer angemeldet ist. Wenn sie nicht angemeldet sind, wird ein Link mitGoogle Login angezeigt.

Durch Drücken des Links werden sie zum Endpunkt von/loginumgeleitet, wodurch der Anmeldefluss initiiert wird. Nach erfolgreicher Anmeldung werden auf der Startseite nun sowohl die Google-E-Mail-Adresse des Nutzers als auch das öffentliche Google-Profilbild angezeigt.

Ohne weiteres können Sie Ihrerapp.py-Datei weiteren Code hinzufügen:

@app.route("/")
def index():
    if current_user.is_authenticated:
        return (
            "

Hello, {}! You're logged in! Email: {}

" "

Google Profile Picture:

" 'Google profile pic
' 'Logout'.format( current_user.name, current_user.email, current_user.profile_pic ) ) else: return 'Google Login'

Sie werden feststellen, dass Sie HTML als Zeichenfolge zurückgeben, die Flask bereitstellen kann. Dascurrent_user.is_authenticated ist eine schöne Ergänzung derFlask-Login-Bibliothek. Auf diese Weise können Sie auf einfache Weise feststellen, ob der aktuelle Benutzer, der mit Ihrer Anwendung interagiert, angemeldet ist oder nicht. Auf diese Weise können Sie bedingte Logik anwenden. In diesem Fall werden einige Informationen angezeigt, die Sie über den Benutzer gespeichert haben, wenn dieser angemeldet ist.

Sie können Felder aus Ihrem Datenbankeintrag für den Benutzer abrufen, indem Sie einfach als Attribute auf das Objektcurrent_userzugreifen, z. B.current_user.email. Dies ist eine weitere Addition vonFlask-Login.

Einloggen

Kommen wir nun zum OAuth 2-Fluss. Die SchaltflächeGoogle Login von oben leitet zu diesem Endpunkt um. Der erste Schritt im Ablauf besteht darin, herauszufinden, wo sich der OAuth 2-Autorisierungsendpunkt von Google befindet.

Hier verschwimmen die Grenzen zwischen den Definitionen von OAuth 2 und OpenID Connect (OIDC). Wie bereits erwähnt, verfügt OIDC über einen Standardendpunkt fürprovider configuration, der eine Reihe von OAuth 2- und OIDC-Informationen enthält. Das Dokument mit diesen Informationen wird von einem Standardendpunkt überall bereitgestellt,.well-known/openid-configuration.

Angenommen, Sie haben den vorherigen Code kopiert, derGOOGLE_DISCOVERY_URL definiert hat, finden Sie hier eine schnelle, naive Funktion zum Abrufen der Anbieterkonfiguration von Google:

def get_google_provider_cfg():
    return requests.get(GOOGLE_DISCOVERY_URL).json()

Tip: Um dies robuster zu machen, sollten Sie dem Google-API-Aufruf eine Fehlerbehandlung hinzufügen, nur für den Fall, dass die Google-API einen Fehler zurückgibt und nicht das gültige Anbieterkonfigurationsdokument.

Das Feld aus dem Provider-Konfigurationsdokument, das Sie benötigen, heißtauthorization_endpoint. Diese enthält die URL, die Sie verwenden müssen, um den OAuth 2-Flow mit Google von Ihrer Clientanwendung aus zu initiieren.

Sie können all diese Logik mit dem folgenden Code zusammenfassen:

@app.route("/login")
def login():
    # Find out what URL to hit for Google login
    google_provider_cfg = get_google_provider_cfg()
    authorization_endpoint = google_provider_cfg["authorization_endpoint"]

    # Use library to construct the request for Google login and provide
    # scopes that let you retrieve user's profile from Google
    request_uri = client.prepare_request_uri(
        authorization_endpoint,
        redirect_uri=request.base_url + "/callback",
        scope=["openid", "email", "profile"],
    )
    return redirect(request_uri)

Glücklicherweise erleichtertoauthlib die eigentliche Anfrage an Google. Sie haben Ihre vorkonfiguriertenclientverwendet, denen Sie bereits Ihre Google Client-ID gegeben haben. Als Nächstes haben Sie die Weiterleitung angegeben, die Google verwenden soll. Schließlich haben Sie Google nach einer Anzahl von OAuth 2scopesgefragt.

Sie können sich jeden Bereich als separate Benutzerinformation vorstellen. In Ihrem Fall fordern Sie bei Google die E-Mail-Adresse und die grundlegenden Profilinformationen des Nutzers an. Der Benutzer muss natürlich zustimmen, Ihnen diese Informationen zu geben.

Note:openid ist ein erforderlicher Bereich, um Google anzuweisen, den OIDC-Fluss zu initiieren, der den Benutzer authentifiziert, indem er sich anmeldet. OAuth 2 standardisiert nicht wirklich, wie die Authentifizierung erfolgt, daher ist dies in diesem Fall für unseren Ablauf erforderlich.

Login-Rückruf

Lassen Sie uns dies in Teilen tun, da es etwas komplizierter ist als die vorherigen Endpunkte.

Sobald Sie zum Autorisierungsendpunkt von Google umleiten, passiert am Ende von Google viel.

Der Anmeldeendpunkt in Ihrer Anwendung ist der Ausgangspunkt für alle Arbeiten von Google, bei denen der Nutzer authentifiziert und um Zustimmung gebeten wird. Sobald sich der Nutzer bei Google anmeldet und sich bereit erklärt, seine E-Mail- und grundlegenden Profilinformationen mit Ihrer Anwendung zu teilen, generiert Google einen eindeutigen Code, den es an Ihre Anwendung zurücksendet.

Zur Erinnerung, hier sind die OIDC-Schritte, über die Sie zuvor gelesen haben:

  1. Sie registrieren eine Drittanbieteranwendung als Client beim Anbieter.

  2. Der Client sendet eine Anfrage an dieauthorization-URL des Anbieters.

  3. Der Anbieter fordert den Benutzer auf, sich zu authentifizieren (zu beweisen, wer er ist).

  4. Der Anbieter bittet den Benutzer, dem in seinem Namen handelnden Kunden zuzustimmen.

  5. Der Anbieter sendet dem Client einen eindeutigen Autorisierungscode

  6. Der Client sendet den Autorisierungscode an dietoken-URL des Anbieters zurück

  7. Der Anbieter sendet die Client-Token zur Verwendung mit anderen URLs im Namen des Benutzers

Wenn Google diesen eindeutigen Code zurücksendet, wird er an diesen Anmelde-Rückruf-Endpunkt in Ihrer Anwendung gesendet. Ihr erster Schritt besteht also darin, den Endpunkt zu definieren und diesecode zu erhalten:

@app.route("/login/callback")
def callback():
    # Get authorization code Google sent back to you
    code = request.args.get("code")

Als Nächstes senden Sie diesen Code an dentoken-Endpunkt von Google zurück. Nachdem Google Ihre Client-Anmeldeinformationen überprüft hat, werden Ihnen Token zurückgesendet, mit denen Sie sich im Namen des Nutzers bei anderen Google-Endpunkten authentifizieren können, einschließlich des Endpunkts vonuserinfo, über den Sie zuvor gelesen haben. In Ihrem Fall haben Sie nur darum gebeten, grundlegende Profilinformationen anzuzeigen. Dies ist also das einzige, was Sie mit den Token tun können.

Zunächst müssen Sie herausfinden, wie hoch der Endpunkt von Google intokenist. Sie werden das Provider-Konfigurationsdokument erneut verwenden:

# Find out what URL to hit to get tokens that allow you to ask for
# things on behalf of a user
google_provider_cfg = get_google_provider_cfg()
token_endpoint = google_provider_cfg["token_endpoint"]

oauthlib kommt in diesem nächsten Codeblock einige Male zu Ihrer Rettung. Zunächst müssen Sie die Token-Anforderung erstellen. Sobald die Anforderung erstellt wurde, verwenden Sie die Bibliothekrequests, um sie tatsächlich zu versenden. Dann hilft Ihnenoauthlib erneut beim Parsen der Token aus der Antwort:

# Prepare and send a request to get tokens! Yay tokens!
token_url, headers, body = client.prepare_token_request(
    token_endpoint,
    authorization_response=request.url,
    redirect_url=request.base_url,
    code=code
)
token_response = requests.post(
    token_url,
    headers=headers,
    data=body,
    auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
)

# Parse the tokens!
client.parse_request_body_response(json.dumps(token_response.json()))

Nachdem Sie über die erforderlichen Tools verfügen, um die Profilinformationen des Nutzers abzurufen, müssen Sie Google danach fragen. Glücklicherweise definiert OIDC einen Endpunkt für Benutzerinformationen und seine URL für einen bestimmten Anbieter ist in der Anbieterkonfiguration standardisiert. Sie können den Speicherort ermitteln, indem Sie das Felduserinfo_endpointim Anbieterkonfigurationsdokument überprüfen. Dann können Sieoauthlib verwenden, um das Token zu Ihrer Anfrage hinzuzufügen, undrequests verwenden, um es zu versenden:

# Now that you have tokens (yay) let's find and hit the URL
# from Google that gives you the user's profile information,
# including their Google profile image and email
userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
uri, headers, body = client.add_token(userinfo_endpoint)
userinfo_response = requests.get(uri, headers=headers, data=body)

Der nächste Schritt auf Ihrer Reise besteht darin, die Antwort vom Endpunkt vonuserinfozu analysieren. Google verwendet ein optionales Feld,email_verified, um zu bestätigen, dass der Nutzer nicht nur ein Konto erstellt hat, sondern auch die E-Mail-Adresse überprüft hat, um die Kontoerstellung abzuschließen. Es ist im Allgemeinen sicher, diese Überprüfung unter bestimmten Bedingungen zu überprüfen, da dies eine weitere Sicherheitsebene ist, die Google bietet.

Davon abgesehen überprüfen Sie dies. Wenn Google angibt, dass der Nutzer verifiziert wurde, analysieren Sie seine Informationen. Die 4 grundlegenden Profilinformationen, die Sie verwenden, sind:

  1. sub:ist der Betreff, eine eindeutige Kennung für den Nutzer in Google

  2. email:ist die Google-E-Mail-Adresse des Nutzers

  3. picture:ist das öffentliche Profilbild des Nutzers in Google

  4. given_name:ist der Vor- und Nachname des Nutzers in Google

All diese Analyse führt zu folgendem Code:

# You want to make sure their email is verified.
# The user authenticated with Google, authorized your
# app, and now you've verified their email through Google!
if userinfo_response.json().get("email_verified"):
    unique_id = userinfo_response.json()["sub"]
    users_email = userinfo_response.json()["email"]
    picture = userinfo_response.json()["picture"]
    users_name = userinfo_response.json()["given_name"]
else:
    return "User email not available or not verified by Google.", 400

Die letzten Schritte in diesem Rückruf sind:

  1. Erstellen Sie einen Nutzer in Ihrer Datenbank mit den Informationen, die Sie gerade von Google erhalten haben

  2. Beginnen Sie eine Benutzersitzung, indem Sie diesen Benutzer anmelden

  3. Benutzer zurück zur Startseite senden (wo Sie jetzt seine öffentlichen Profilinformationen anzeigen)

Der Code zum Ausführen dieser Schritte lautet wie folgt:

# Create a user in your db with the information provided
# by Google
user = User(
    id_=unique_id, name=users_name, email=users_email, profile_pic=picture
)

# Doesn't exist? Add it to the database.
if not User.get(unique_id):
    User.create(unique_id, users_name, users_email, picture)

# Begin user session by logging the user in
login_user(user)

# Send user back to homepage
return redirect(url_for("index"))

Sie erstellen hier also eine neue Zeile in Ihrer Datenbank für den Benutzer, sofern diese noch nicht vorhanden ist. Anschließend starten Sie eine Sitzung mit Flask-Login.

Ausloggen

Der Abmeldeendpunkt ist viel weniger Code als die letzten Endpunkte. Sie rufen einfach eine Abmeldefunktion auf und leiten zurück zur Startseite. Gemacht und gemacht. Hier ist es:

@app.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(url_for("index"))

Das@login_requireddecorator ist hier etwas Wichtiges zu erwähnen. Es ist ein weiteres Tool aus der Toolbox vonFlask-Loginund stellt sicher, dass nur angemeldete Benutzer auf diesen Endpunkt zugreifen können. Sie können dies verwenden, wenn nur angemeldete Benutzer auf etwas zugreifen sollen. In diesem Fall können sich nur angemeldete Benutzer abmelden.

Testen Sie Ihre Anwendung vor Ort

Sie können Ihre Flask-Anwendung auf Ihrem lokalen Computer ausführen, um den Anmeldefluss zu testen, indem Sieapp.py einen endgültigen Code hinzufügen:

if __name__ == "__main__":
    app.run(ssl_context="adhoc")

Sie können Ihre Flask-Anwendung mit dem folgenden Befehl in Ihrem Terminal ausführen:

$ python app.py

Note: Aufgrund der naiven Datenbankinitialisierungslogik wird beim ersten Ausführen dieses Befehls die Datenbank erstellt. Um Ihre App zu starten, müssen Sie denselben Befehlagain ausführen.

Die Flasche sollte auf Ihrem Terminal gedruckt werden, auf dem der Entwicklungsserver ausgeführt wird. Es solltehttps://127.0.0.1:5000/ sein.

Beachten Sie, dass auf dem Entwicklungsserver von Flaskand lokal ausgeführt wird undhttps verwendet wird, um eine verschlüsselte Verbindung mit Google sicherzustellen. Dies wird durch das Argumentssl_context="adhoc" zuapp.run im obigen Code erreicht. Dazu muss das PaketPyOpenSSL installiert sein.

Der Nachteil ist, dass das verwendete Zertifikat im laufenden Betrieb generiert wird. Wenn Sie also in Ihrem Browser zuhttps://127.0.0.1:5000/ wechseln, wird wahrscheinlich ein großer Warnbildschirm angezeigt, dass Ihre Verbindung unsicher oder nicht privat ist. Sie können diese Warnungen effektiv ignorieren.

Sobald Sie den Warnbildschirm überschritten haben, sollte eine einzelne Schaltfläche mit der AufschriftGoogle Login angezeigt werden. Durch Drücken dieser Taste gelangen Sie zum offiziellen Google-Login. Nachdem Sie sich angemeldet haben, werden Sie von Google aufgefordert, der Anwendung von Drittanbietern zuzustimmen, um Zugriff auf Ihre E-Mail- und Profilinformationen zu erhalten.

Nach der Einwilligung werden Sie zurück zu Ihrer Flask-Anwendung weitergeleitet, auf der auf der Seite Ihre Google-E-Mail-Adresse und Ihr öffentliches Profilbild angezeigt werden sollen. Mit einerLogout-Schaltfläche können Sie sich abmelden.

Fazit

Das Zulassen, dass Benutzer ihre vorhandenen Konten verwenden, um sich bei Ihrer Webanwendung anzumelden, hat viele Vorteile. Am wichtigsten ist, dass die Sicherheit und Komplexität der Kontoverwaltung nicht auf Ihren Schultern liegen muss. Auf diese Weise können Sie Ihre ausgefallene neue Webanwendung schreiben, ohne sich um die Details der Zwei-Faktor-Authentifizierung und dergleichen kümmern zu müssen.

Die Anwendung, die Sie in diesem Artikel gemacht haben, ist ein guter Ausgangspunkt. Sie können auf das Feld unten klicken, um den Code zu erhalten:

Ihr nächster Schritt könnte darin bestehen, Folgendes zu tun:

  • Überarbeiten Sie die Datenbankinitialisierung so, dass sie getrennt von der Ausführung der Anwendung erfolgt

  • Trennen Sie HTML / CSS vom Python-Code, um die Verwaltung zu vereinfachen:

  • Hosten Sie Ihre Anwendung in der Cloud

  • Kaufen Sie einen Domainnamen

  • Verwenden Sie ein echtes SSL-Zertifikat und entfernen Sie diese lästige Warnung

In diesem Artikel haben Sie die Grundlagen von OAuth 2 und OpenID Connect erläutert. Sie haben gesehen, wie Sie mit bekannten Python-Paketen eine Webanwendung erstellen, mit der sich Benutzer mit ihrem vorhandenen Google-Konto anmelden können. Am wichtigsten ist, dass Sie Beispielcode haben, der als Ausgangspunkt für Ihre nächste Webanwendung dient!