Jak utworzyć przycisk SSO — samouczek dotyczący logowania do kolby
Opublikowany: 2022-03-11Aplikacje często potrzebują funkcji logowania, aby użytkownicy mogli zapisywać dane, tworzyć własne profile, a może po prostu ograniczać dostęp do wrażliwych zasobów. W nowoczesnej aplikacji użytkownicy oczekują standardowych funkcji związanych z logowaniem, takich jak weryfikacja poczty e-mail, resetowanie hasła lub uwierzytelnianie wieloskładnikowe. Te funkcje, choć niezbędne, nie są łatwe do uzyskania i zwykle nie są głównym zadaniem aplikacji.
Po stronie użytkownika mogą nie chcieć przechodzić przez długi proces rejestracji, ponieważ muszą utworzyć i zapamiętać kolejną parę adresów e-mail i hasła. Bez odpowiedniego menedżera haseł użytkownicy mają tendencję do ponownego używania tego samego hasła, co jest straszne pod względem bezpieczeństwa.
Pojedyncze logowanie (SSO), znane użytkownikom głównie jako logowanie za pomocą przycisków mediów społecznościowych , zostało wymyślone jako rozwiązanie tego problemu. Dla użytkowników uniknięcie kolejnego bolesnego procesu rejestracji było łatwe. Dla firm usunięcie tarcia dla użytkowników jest zawsze ogromną wygraną, a dla programistów wszystkie funkcje związane z logowaniem są teraz delegowane do dostawcy tożsamości (Facebook, Google, Twitter itp.), co oznacza mniej kodu! Twoja aplikacja po prostu ufa dostawcy tożsamości w zakresie weryfikacji tożsamości użytkownika.
Logowanie jednokrotne jest zwykle obsługiwane przez protokół OpenId Connect (OIDC) lub SAML. SAML jest używany głównie w aplikacjach korporacyjnych. OIDC jest oparty na protokole OAuth2 i jest używany przez dostawców tożsamości społecznościowych, takich jak Facebook, Google itp. W tym poście skupimy się na protokole OIDC/OAuth2.
W tym samouczku logowania Flask napiszemy przewodnik krok po kroku, jak dodać przycisk logowania SSO do aplikacji Flask z SimpleLogin i Facebook jako dostawcą tożsamości. Można to zrobić bez użycia zewnętrznej biblioteki, ale aby uprościć zawiłości OAuth, użyjemy Requests-OAuthlib, biblioteki do integracji dostawców OAuth. Jeśli jesteś zainteresowany wdrożeniem SSO od podstaw, sprawdź Implementuj logowanie SSO – surowy sposób .
Na końcu tego artykułu powinieneś mieć aplikację Flask, która ma następujące strony:
- Strona główna z przyciskami logowania
- Strona z informacjami o użytkowniku, na której po pomyślnym zalogowaniu użytkownik będzie mógł zobaczyć informacje, takie jak imię i nazwisko, adres e-mail i awatar
Cały kod tego samouczka można znaleźć w repozytorium flask-social-login-example.
Demo jest również dostępne tutaj. Zapraszam do zremiksowania kodu na Glitch.
Krok 1: Aplikacja Bootstrap Flask
Zainstaluj flask
i Requests-OAuthlib
. Możesz także użyć virtualenv
lub pipenv
, aby odizolować środowisko.
pip install kolba request_oauthlib
Utwórz app.py
i trasę, która wyświetla przycisk logowania na stronie głównej:
import flask app = flask.Flask(__name__) @app.route("/") def index(): return """ <a href="/login">Login</a> """ if __name__ == '__main__': app.run(debug=True)
Uruchommy tę aplikację i sprawdźmy, czy wszystko działa dobrze:
python app.py
Powinieneś zobaczyć tę stronę podczas otwierania http://localhost:5000. Pełny kod znajduje się na step1.py.
Krok 2: Poświadczenia dostawcy tożsamości
Obecnie istnieją setki (jeśli nie tysiące) dostawców tożsamości, z których najpopularniejsze to Facebook, Google, GitHub i Instagram. W tym poście wybrano SimpleLogin ze względu na przyjazność dla programistów. Ten sam kod będzie jednak działał z dowolnym dostawcą tożsamości OAuth2. (Zastrzeżenie: tak się składa, że jestem współzałożycielem SimpleLogin, co – hm – mogło mieć wpływ na moją decyzję o jego użyciu.)
Przejdź do SimpleLogin i utwórz konto, jeśli jeszcze go nie masz, a następnie utwórz nową aplikację na karcie Deweloper.
Na stronie szczegółów aplikacji skopiuj swój identyfikator AppID i AppSecret i zapisz je w środowisku zmiennych. W terminologii OAuth klient faktycznie oznacza aplikację innej firmy, tj. Twoją aplikację. Możemy umieścić te wartości bezpośrednio w kodzie, ale dobrą praktyką jest zapisywanie poświadczeń w zmiennych środowiskowych. Jest to również trzeci czynnik w The Twelve Factors.
export CLIENT_ID={your AppID} export CLIENT_SECRET={your AppSecret}
W app.py
, dodaj te wiersze na górze pliku , aby uzyskać client id
client secret
klucz klienta .
import os CLIENT_ID = os.environ.get("CLIENT_ID") CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
Dodaj również te adresy URL OAuth na górze app.py
, które będą używane w następnym kroku. Można je również skopiować na stronie punktów końcowych OAuth.
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"
Ponieważ nie chcemy się teraz martwić konfiguracją SSL, powiedzmy Requests-OAuthlib
, że używanie zwykłego HTTP jest w porządku:
# This allows us to use a plain HTTP callback os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
Jak zwykle kod tego kroku znajduje się na step2.py.
Krok 3: Przekierowanie logowania
Gdy użytkownik kliknie przycisk logowania:
- Użytkownik zostanie przekierowany na stronę autoryzacji dostawcy logowania tożsamości z pytaniem, czy chce udostępnić swoje informacje Twojej aplikacji.
- Po zatwierdzeniu przez użytkownika zostaną oni przekierowani z powrotem na stronę w Twojej aplikacji wraz z
code
w adresie URL, którego aplikacja będzie używać do wymiany naaccess token
, który pozwala później uzyskać informacje o użytkowniku od dostawcy usług.
Dlatego potrzebujemy dwóch tras: trasy login
, która przekierowuje użytkownika do dostawcy tożsamości oraz trasy callback
, która odbiera code
i wymienia go na access token
. Trasa wywołania zwrotnego jest również odpowiedzialna za wyświetlanie informacji o użytkowniku.

@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> """
Kliknięcie przycisku logowania powinno spowodować przejście przez następujący proces. Pełny kod można znaleźć na GitHub pod adresem step3.py.
Zaloguj się przez facebook
Konfiguracja logowania na Facebooku, Google i Twitterze jest nieco skomplikowana i wymaga dodatkowych kroków, takich jak konfiguracja SSL lub wybór odpowiednich zakresów. Są one poza zakresem tego artykułu.
Oprócz zaawansowanego interfejsu użytkownika, najtrudniejszą częścią integracji Facebooka może być znalezienie sposobu na lokalną obsługę aplikacji internetowej przez HTTPS, ponieważ nowa wersja Facebook SDK nie zezwala na lokalny zwykły HTTP. Polecam używać Ngrok, darmowego narzędzia, aby mieć szybki adres URL HTTPS.
Krok 1: Utwórz aplikację na Facebooka
Wejdź na https://developers.facebook.com
i utwórz nową aplikację:
Następnie wybierz „Zintegruj logowanie do Facebooka” na następnym ekranie:
Krok 2: Poświadczenia Facebook OAuth
Kliknij „Ustawienia/Podstawowe” po lewej stronie i skopiuj identyfikator aplikacji oraz klucz tajny aplikacji . W rzeczywistości są to client-id
client-secret
i klucz klienta protokołu OAuth .
Zaktualizuj client-id
client-secret
klucz klienta .
export FB_CLIENT_ID={your facebook AppId} export FB_CLIENT_SECRET={your facebook AppSecret}
Zaktualizuj AUTHORIZATION_BASE_URL i TOKEN_URL:
FB_AUTHORIZATION_BASE_URL = "https://www.facebook.com/dialog/oauth" FB_TOKEN_URL = "https://graph.facebook.com/oauth/access_token"
Strona główna:
@app.route("/") def index(): return """ <a href="/fb-login">Login with Facebook</a> """
Krok 3: Logowanie i punkty końcowe oddzwaniania
Jeśli aplikacja jest obsługiwana za ngrok
za pomocą polecenia ngrok http 5000
, musimy ustawić bieżący adres URL na adres URL ngrok.
# Your ngrok url, obtained after running "ngrok http 5000" URL = "https://abcdefgh.ngrok.io"
Pamiętaj, aby dodać adres URL do loginu/ustawień Facebooka, prawidłowe ustawienie identyfikatorów URI przekierowania OAuth:
Aby mieć dostęp do adresu e-mail użytkownika, musisz dodać email
do scope
:
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)
Trasa callback
jest nieco bardziej złożona, ponieważ Facebook wymaga poprawki zgodności:
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> """
Teraz po kliknięciu opcji Zaloguj się przez Facebooka powinieneś być w stanie przejść przez cały przepływ.
Pełny kod znajduje się na facebook.py.
Wniosek
Gratulacje — udało Ci się zintegrować logowanie SSO z aplikacją Flask!
W celu uproszczenia w tym samouczku nie wspomniano o innych koncepcjach protokołu OAuth, takich jak zakres i stan, które są ważne w celu ochrony przed atakami fałszowania żądań między lokacjami. Prawdopodobnie będziesz również musiał przechowywać informacje o użytkowniku w bazie danych, która nie została omówiona w tym artykule.
Aplikacja musi być również obsługiwana przez https na produkcji, co można łatwo zrobić dzisiaj dzięki Let's Encrypt.
Udanego uwierzytelnienia OAuthing!