So erstellen Sie eine SSO-Schaltfläche – Ein Flask-Login-Tutorial

Veröffentlicht: 2022-03-11

Anwendungen benötigen häufig eine Anmeldefunktion, damit Benutzer Daten speichern, ihre eigenen Profile erstellen oder vielleicht nur den Zugriff auf sensible Ressourcen einschränken können. In einer modernen App erwarten Benutzer standardmäßige Anmeldefunktionen wie E-Mail-Bestätigung, Kennwortzurücksetzung oder Multi-Faktor-Authentifizierung. Diese Funktionen sind zwar notwendig, aber nicht einfach richtig hinzubekommen und normalerweise nicht das Hauptgeschäft der App.

Auf der Benutzerseite möchten sie möglicherweise auch nicht den langwierigen Registrierungsprozess durchlaufen, da sie ein weiteres E-Mail- und Passwort-Paar erstellen und sich merken müssen. Ohne einen geeigneten Passwort-Manager neigen Benutzer dazu, dasselbe Passwort wiederzuverwenden, was in Bezug auf die Sicherheit schrecklich ist.

Als Lösung für dieses Problem wurde Single Sign-On (SSO) erfunden, das den Benutzern meist als Anmeldung mit Social-Media- Schaltflächen bekannt ist. Für die Benutzer war es einfach, keinen weiteren schmerzhaften Registrierungsprozess zu durchlaufen. Für Unternehmen ist es immer ein großer Gewinn, Reibungsverluste für Benutzer zu beseitigen – und für Entwickler werden alle Login-bezogenen Funktionen jetzt an den Identitätsanbieter (Facebook, Google, Twitter usw.) delegiert , was weniger Code bedeutet! Ihre App vertraut einfach darauf, dass der Identitätsanbieter seine Aufgabe zur Überprüfung der Benutzeridentität erfüllt.

SSO wird normalerweise vom OpenId Connect (OIDC)- oder SAML-Protokoll unterstützt. SAML wird hauptsächlich in Unternehmensanwendungen verwendet. OIDC baut auf OAuth2 auf und wird von Anbietern sozialer Identitäten wie Facebook, Google usw. verwendet. In diesem Beitrag konzentrieren wir uns auf das OIDC/OAuth2-Protokoll.

In diesem Tutorial zur Flask-Anmeldung schreiben wir eine Schritt-für-Schritt-Anleitung zum Hinzufügen einer SSO-Anmeldeschaltfläche zu einer Flask-Anwendung mit SimpleLogin und Facebook als Identitätsanbieter. Dies kann ohne Verwendung einer externen Bibliothek erfolgen, aber um die Feinheiten von OAuth zu vereinfachen, verwenden wir Requests-OAuthlib, eine Bibliothek zur Integration von OAuth-Anbietern. Wenn Sie daran interessiert sind, SSO von Grund auf neu zu implementieren, lesen Sie bitte Implement SSO Login – the raw way .

Am Ende dieses Artikels sollten Sie eine Flask-App haben, die die folgenden Seiten hat:

  • Homepage mit Login-Buttons
  • Benutzerinformationsseite, auf der der Benutzer nach erfolgreicher Anmeldung Informationen wie Name, E-Mail und Avatar sehen kann

Den gesamten Code für dieses Tutorial finden Sie im Repository Flask-Social-Login-Example.

Eine Demo ist auch hier verfügbar. Fühlen Sie sich frei, den Code auf Glitch zu remixen.

Schritt 1: Bootstrap Flask-App

Flask und Requests-OAuthlib flask Sie können auch virtualenv oder pipenv , um die Umgebung zu isolieren.

pip install Flask-Requests_oauthlib

Erstellen Sie app.py und die Route, die eine Anmeldeschaltfläche auf der Startseite anzeigt:

 import flask app = flask.Flask(__name__) @app.route("/") def index(): return """ <a href="/login">Login</a> """ if __name__ == '__main__': app.run(debug=True)

Lassen Sie uns diese App ausführen und überprüfen, ob alles gut funktioniert:

 python app.py

Sie sollten diese Seite sehen, wenn Sie http://localhost:5000 öffnen. Der vollständige Code befindet sich auf step1.py.

Melden Sie sich mit SimpleLogin an

Schritt 2: Identitätsanbieter-Anmeldeinformationen

Derzeit gibt es Hunderte (wenn nicht Tausende) von Identitätsanbietern, wobei die beliebtesten Facebook, Google, GitHub und Instagram sind. Für diesen Beitrag wurde SimpleLogin aufgrund seiner Entwicklerfreundlichkeit ausgewählt. Derselbe Code funktioniert jedoch mit jedem OAuth2-Identitätsanbieter. (Haftungsausschluss: Ich bin zufällig der Mitbegründer von SimpleLogin, was – ähm – ein Faktor bei meiner Entscheidung gewesen sein könnte, es zu verwenden.)

Bitte gehen Sie zu SimpleLogin und erstellen Sie ein Konto, falls Sie noch keines haben, und erstellen Sie dann eine neue App auf der Registerkarte „Entwickler“.

Kopieren Sie bitte auf der App-Detailseite Ihre AppID und Ihr AppSecret und speichern Sie diese in der Variablenumgebung. In der OAuth-Terminologie bedeutet Client eigentlich eine Drittanbieter-App, dh Ihre App. Wir können diese Werte direkt in den Code einfügen, aber es empfiehlt sich, Anmeldeinformationen in Umgebungsvariablen zu speichern. Dies ist auch der dritte Faktor in den Zwölf Faktoren.

OAuth2-Einstellungen

 export CLIENT_ID={your AppID} export CLIENT_SECRET={your AppSecret}

Fügen Sie in app.py diese Zeilen oben in die Datei ein, um die client id und das client secret zu erhalten.

 import os CLIENT_ID = os.environ.get("CLIENT_ID") CLIENT_SECRET = os.environ.get("CLIENT_SECRET")

Bitte fügen Sie diese OAuth-URLs oben in app.py , die im nächsten Schritt verwendet werden. Sie können auch auf der Seite OAuth-Endpunkte kopiert werden.

 AUTHORIZATION_BASE_URL = "https://app.simplelogin.io/oauth2/authorize" TOKEN_URL = "https://app.simplelogin.io/oauth2/token" USERINFO_URL = "https://app.simplelogin.io/oauth2/userinfo"

Da wir uns jetzt keine Gedanken über die Einrichtung von SSL machen wollen, teilen wir Requests-OAuthlib mit, dass es in Ordnung ist, einfaches HTTP zu verwenden:

 # This allows us to use a plain HTTP callback os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

Wie üblich befindet sich der Code für diesen Schritt auf step2.py.

Schritt 3: Anmeldeumleitung

Wenn ein Benutzer auf die Anmeldeschaltfläche klickt:

  1. Der Benutzer wird auf die Autorisierungsseite des Identitäts-Login-Anbieters umgeleitet und gefragt, ob der Benutzer seine Informationen mit Ihrer App teilen möchte.
  2. Nach der Genehmigung durch den Benutzer werden sie zusammen mit einem code in der URL, die Ihre App verwendet, um sie gegen ein access token auszutauschen, das es Ihnen ermöglicht, später Benutzerinformationen vom Dienstanbieter zu erhalten, zu einer Seite Ihrer App zurückgeleitet.

Wir brauchen also zwei Routen: eine login -Route, die den Benutzer zum Identitätsanbieter umleitet, und eine callback -Route, die den code und gegen den access token austauscht. Die Rückrufroute ist auch für die Anzeige von Benutzerinformationen zuständig.

 @app.route("/login") def login(): simplelogin = requests_oauthlib.OAuth2Session( CLIENT_ID, redirect_uri="http://localhost:5000/callback" ) authorization_url, _ = simplelogin.authorization_url(AUTHORIZATION_BASE_URL) return flask.redirect(authorization_url) @app.route("/callback") def callback(): simplelogin = requests_oauthlib.OAuth2Session(CLIENT_ID) simplelogin.fetch_token( TOKEN_URL, client_secret=CLIENT_SECRET, authorization_response=flask.request.url ) user_info = simplelogin.get(USERINFO_URL).json() return f""" User information: <br> Name: {user_info["name"]} <br> Email: {user_info["email"]} <br> Avatar <img src="{user_info.get('avatar_url')}"> <br> <a href="/">Home</a> """

Wenn Sie auf die Anmeldeschaltfläche klicken, sollten Sie durch den folgenden Ablauf geführt werden. Den vollständigen Code finden Sie auf GitHub unter step3.py.

Melden Sie sich mit SimpleLogin an, um Benutzerinformationen zuzulassen

Mit Facebook einloggen

Die Einrichtung der Facebook-, Google- und Twitter-Anmeldung ist etwas komplex und erfordert zusätzliche Schritte wie die Einrichtung von SSL oder die Auswahl der richtigen Bereiche. Diese gehen über den Rahmen dieses Artikels hinaus.

Abgesehen von einer ausgefeilten Benutzeroberfläche könnte der schwierigste Teil bei der Integration von Facebook darin bestehen, einen Weg zu finden, Ihre Webanwendung lokal auf HTTPS bereitzustellen, da die neue Version des Facebook-SDK kein lokales einfaches HTTP zulässt. Ich empfehle die Verwendung von Ngrok, einem kostenlosen Tool, um eine schnelle HTTPS-URL zu haben.

Schritt 1: Erstellen Sie eine Facebook-App

Bitte gehen Sie zu https://developers.facebook.com und erstellen Sie eine neue App:

Erstellen Sie eine neue App-ID

Wählen Sie dann auf dem nächsten Bildschirm „Facebook-Login integrieren“:

Facebook-Login integrieren

Schritt 2: Facebook-OAuth-Anmeldeinformationen

Klicken Sie links auf „Settings/Basic“ und kopieren Sie die App-ID und das App-Secret . Sie sind eigentlich OAuth client-id und client-secret .

Grundeinstellungen

Aktualisieren Sie die client-id und client-secret .

 export FB_CLIENT_ID={your facebook AppId} export FB_CLIENT_SECRET={your facebook AppSecret}

Aktualisieren Sie die AUTHORIZATION_BASE_URL und TOKEN_URL:

 FB_AUTHORIZATION_BASE_URL = "https://www.facebook.com/dialog/oauth" FB_TOKEN_URL = "https://graph.facebook.com/oauth/access_token"

Die Homepage:

 @app.route("/") def index(): return """ <a href="/fb-login">Login with Facebook</a> """

Schritt 3: Anmelde- und Rückrufendpunkte

Wenn die App mit dem Befehl ngrok http 5000 hinter ngrok bereitgestellt wird, müssen wir die aktuelle URL auf die ngrok-URL setzen.

 # Your ngrok url, obtained after running "ngrok http 5000" URL = "https://abcdefgh.ngrok.io"

Bitte stellen Sie sicher, dass Sie die URL zu Ihrer Facebook-Anmeldung/Einstellungen, gültige OAuth-Umleitungs-URIs-Einstellung hinzufügen:

Gültige OAuth-Umleitungs-URIs

Um Zugriff auf eine Benutzer-E-Mail zu haben, müssen Sie die email zum scope hinzufügen:

 FB_SCOPE = ["email"] @app.route("/fb-login") def login(): facebook = requests_oauthlib.OAuth2Session( FB_CLIENT_ID, redirect_uri=URL + "/fb-callback", scope=FB_SCOPE ) authorization_url, _ = facebook.authorization_url(FB_AUTHORIZATION_BASE_URL) return flask.redirect(authorization_url)

Die callback Route ist etwas komplexer, da Facebook einen Compliance-Fix benötigt:

 from requests_oauthlib.compliance_fixes import facebook_compliance_fix @app.route("/fb-callback") def callback(): facebook = requests_oauthlib.OAuth2Session( FB_CLIENT_ID, scope=FB_SCOPE, redirect_uri=URL + "/fb-callback" ) # we need to apply a fix for Facebook here facebook = facebook_compliance_fix(facebook) facebook.fetch_token( FB_TOKEN_URL, client_secret=FB_CLIENT_SECRET, authorization_response=flask.request.url, ) # Fetch a protected resource, ie user profile, via Graph API facebook_user_data = facebook.get( "https://graph.facebook.com/me?fields=id,name,email,picture{url}" ).json() email = facebook_user_data["email"] name = facebook_user_data["name"] picture_url = facebook_user_data.get("picture", {}).get("data", {}).get("url") return f""" User information: <br> Name: {name} <br> Email: {email} <br> Avatar <img src="{picture_url}"> <br> <a href="/">Home</a> """

Wenn Sie jetzt auf Mit Facebook anmelden klicken, sollten Sie in der Lage sein, den gesamten Ablauf zu durchlaufen.

Login mit Facebook-Prozess

Der vollständige Code ist auf facebook.py.

Fazit

Herzlichen Glückwunsch – Sie haben die SSO-Anmeldung erfolgreich in eine Flask-App integriert!

Der Einfachheit halber werden in diesem Tutorial keine anderen OAuth-Konzepte wie Bereich und Status erwähnt, die wichtig sind, um sich gegen Cross-Site-Request-Forgery-Angriffe zu verteidigen. Sie müssten die Benutzerinformationen wahrscheinlich auch in einer Datenbank speichern, die in diesem Artikel nicht behandelt wird.

Die App muss auch in der Produktion auf https bereitgestellt werden, was heute mit Let's Encrypt recht einfach möglich ist.

Viel Spaß beim OAuthen!