Jak utworzyć przycisk SSO — samouczek dotyczący logowania do kolby

Opublikowany: 2022-03-11

Aplikacje 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.

Zaloguj się za pomocą SimpleLogin

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.

Ustawienia OAuth2

 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:

  1. Użytkownik zostanie przekierowany na stronę autoryzacji dostawcy logowania tożsamości z pytaniem, czy chce udostępnić swoje informacje Twojej aplikacji.
  2. 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 na access 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ę za pomocą SimpleLogin, aby zezwolić na informacje użytkownika

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ę:

Utwórz nowy identyfikator aplikacji

Następnie wybierz „Zintegruj logowanie do Facebooka” na następnym ekranie:

Zintegruj logowanie do Facebooka

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 .

Podstawowe ustawienia

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:

Prawidłowe identyfikatory 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.

Zaloguj się za pomocą procesu Facebook

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!