Comment créer un bouton SSO - Un tutoriel de connexion Flask
Publié: 2022-03-11Les applications ont souvent besoin d'une fonctionnalité de connexion pour que les utilisateurs puissent enregistrer des données, créer leurs propres profils ou peut-être simplement pour restreindre l'accès à des ressources sensibles. Dans une application moderne, les utilisateurs s'attendent à disposer de fonctionnalités standard liées à la connexion, telles que la vérification des e-mails, la réinitialisation du mot de passe ou l'authentification multifacteur. Ces fonctionnalités, bien que nécessaires, ne sont pas faciles à maîtriser et ne constituent généralement pas l'activité principale de l'application.
Du côté des utilisateurs, ils ne voudront peut-être pas non plus passer par le long processus d'inscription, car ils doivent créer et mémoriser une autre paire d'adresses e-mail et de mots de passe. Sans un bon gestionnaire de mots de passe, les utilisateurs ont tendance à réutiliser le même mot de passe, ce qui est terrible en termes de sécurité.
L'authentification unique (SSO), principalement connue des utilisateurs sous le nom de connexion avec des boutons de médias sociaux , a été inventée pour résoudre ce problème. Pour les utilisateurs, il était facile de ne pas passer par un autre processus d'inscription pénible. Pour les entreprises, la suppression des frictions pour les utilisateurs est toujours une énorme victoire et, pour les développeurs, toutes les fonctionnalités liées à la connexion sont désormais déléguées au fournisseur d'identité (Facebook, Google, Twitter, etc.), ce qui signifie moins de code ! Votre application fait simplement confiance au fournisseur d'identité pour effectuer son travail de vérification de l'identité de l'utilisateur.
L'authentification unique est généralement alimentée par le protocole OpenId Connect (OIDC) ou SAML. SAML est principalement utilisé dans les applications d'entreprise. OIDC est construit sur OAuth2 et utilisé par des fournisseurs d'identité sociale comme Facebook, Google, etc. Dans cet article, nous nous concentrerons sur le protocole OIDC/OAuth2.
Dans ce didacticiel de connexion Flask, nous allons rédiger un guide étape par étape pour ajouter un bouton de connexion SSO dans une application Flask avec SimpleLogin et Facebook comme fournisseur d'identité. Cela peut être fait sans utiliser de bibliothèque externe, mais afin de simplifier les subtilités d'OAuth, nous utiliserons Requests-OAuthlib, une bibliothèque pour intégrer les fournisseurs OAuth. Si vous êtes intéressé par la mise en œuvre de SSO à partir de zéro, veuillez consulter Implémenter la connexion SSO - la manière brute .
À la fin de cet article, vous devriez avoir une application Flask contenant les pages suivantes :
- Page d'accueil avec boutons de connexion
- Page d'informations sur l'utilisateur où, une fois la connexion réussie, l'utilisateur pourra voir des informations telles que le nom, l'e-mail et l'avatar
Tout le code de ce tutoriel se trouve sur le référentiel flask-social-login-example.
Une démo est également disponible ici. N'hésitez pas à remixer le code sur Glitch.
Étape 1 : application Bootstrap Flask
Installez flask
et Requests-OAuthlib
. Vous pouvez également utiliser virtualenv
ou pipenv
pour isoler l'environnement.
pip install fiole requests_oauthlib
Créez app.py
et la route qui affiche un bouton de connexion sur la page d'accueil :
import flask app = flask.Flask(__name__) @app.route("/") def index(): return """ <a href="/login">Login</a> """ if __name__ == '__main__': app.run(debug=True)
Exécutons cette application et vérifions que tout fonctionne bien :
python app.py
Vous devriez voir cette page lors de l'ouverture de http://localhost:5000. Le code complet est sur step1.py.
Étape 2 : Identifiant du fournisseur d'identité
Il existe actuellement des centaines (voire des milliers) de fournisseurs d'identité, les plus populaires étant Facebook, Google, GitHub et Instagram. Pour cet article, SimpleLogin est choisi en raison de sa convivialité pour les développeurs. Cependant, le même code fonctionnera avec n'importe quel fournisseur d'identité OAuth2. (Avis de non-responsabilité : il se trouve que je suis le cofondateur de SimpleLogin, ce qui, euh, a peut-être été un facteur dans ma décision de l'utiliser.)
Veuillez vous rendre sur SimpleLogin et créer un compte si vous n'en avez pas déjà un, puis créez une nouvelle application dans l'onglet Développeur.
Sur la page de détail de l'application, veuillez copier votre AppID et AppSecret et les enregistrer dans l'environnement variable. Dans la terminologie OAuth, client signifie en fait une application tierce, c'est-à-dire votre application. Nous pouvons mettre ces valeurs directement dans le code, mais il est recommandé d'enregistrer les informations d'identification dans des variables d'environnement. C'est aussi le troisième facteur des Douze Facteurs.
export CLIENT_ID={your AppID} export CLIENT_SECRET={your AppSecret}
Dans app.py
, veuillez ajouter ces lignes en haut du fichier pour obtenir client id
client secret
.
import os CLIENT_ID = os.environ.get("CLIENT_ID") CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
Veuillez également ajouter ces URL OAuth en haut de app.py
qui seront utilisées à l'étape suivante. Ils peuvent également être copiés sur la page des terminaux 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"
Comme nous ne voulons pas nous soucier de la configuration de SSL maintenant, disons à Requests-OAuthlib
qu'il est acceptable d'utiliser du HTTP simple :
# This allows us to use a plain HTTP callback os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
Comme d'habitude, le code de cette étape se trouve sur step2.py.
Étape 3 : redirection de connexion
Lorsqu'un utilisateur clique sur le bouton de connexion :
- L'utilisateur sera redirigé vers la page d'autorisation du fournisseur de connexion d'identité lui demandant s'il souhaite partager ses informations avec votre application.
- Après approbation de l'utilisateur, ils seront ensuite redirigés vers une page de votre application avec un
code
dans l'URL que votre application utilisera pour échanger unaccess token
qui vous permettra ultérieurement d'obtenir des informations sur l'utilisateur auprès du fournisseur de services.
Nous avons donc besoin de deux routes : une route de login
qui redirige l'utilisateur vers le fournisseur d'identité et une route de callback
qui reçoit le code
et l'échange contre access token
. La route de rappel est également responsable de l'affichage des informations utilisateur.

@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> """
En cliquant sur le bouton de connexion, vous devriez suivre le flux suivant. Le code complet peut être trouvé sur GitHub à step3.py.
Se connecter avec Facebook
La configuration de la connexion à Facebook, Google et Twitter est un peu complexe et nécessite des étapes supplémentaires telles que la configuration de SSL ou le choix des bonnes portées. Ceux-ci sortent du cadre de cet article.
Outre une interface utilisateur sophistiquée, la partie la plus difficile de l'intégration de Facebook pourrait être de trouver un moyen de servir votre application Web sur HTTPS localement, car la nouvelle version de Facebook SDK n'autorise pas le HTTP brut local. Je recommande d'utiliser Ngrok, un outil gratuit pour avoir une URL HTTPS rapide.
Étape 1 : créer une application Facebook
Veuillez vous rendre sur https://developers.facebook.com
et créer une nouvelle application :
Choisissez ensuite « Intégrer Facebook Login » sur l'écran suivant :
Étape 2 : identifiant Facebook OAuth
Cliquez sur "Paramètres/Basique" sur la gauche, et copiez l' ID d' application et le secret d'application. Il s'agit en fait de OAuth client-id
et client-secret
.
Mettez à jour le client-id
et client-secret
.
export FB_CLIENT_ID={your facebook AppId} export FB_CLIENT_SECRET={your facebook AppSecret}
Mettez à jour AUTHORIZATION_BASE_URL et TOKEN_URL :
FB_AUTHORIZATION_BASE_URL = "https://www.facebook.com/dialog/oauth" FB_TOKEN_URL = "https://graph.facebook.com/oauth/access_token"
La page d'accueil :
@app.route("/") def index(): return """ <a href="/fb-login">Login with Facebook</a> """
Étape 3 : connexion et points de terminaison de rappel
Si l'application est servie derrière ngrok
à l'aide de la commande ngrok http 5000
, nous devons définir l'URL actuelle sur l'URL ngrok.
# Your ngrok url, obtained after running "ngrok http 5000" URL = "https://abcdefgh.ngrok.io"
Assurez-vous d'ajouter l'URL à votre connexion/paramètres Facebook, paramètre d'URI de redirection OAuth valide :
Afin d'avoir accès à l'e-mail d'un utilisateur, vous devez ajouter l'e- email
dans la 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)
La route de callback
est un peu plus complexe car Facebook nécessite un correctif de conformité :
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> """
Désormais, lorsque vous cliquez sur Se connecter avec Facebook, vous devriez pouvoir parcourir l'ensemble du flux.
Le code complet est sur facebook.py.
Conclusion
Félicitations, vous avez intégré avec succès la connexion SSO dans une application Flask !
Par souci de simplicité, ce didacticiel ne mentionne pas d'autres concepts OAuth tels que la portée et l'état, qui sont importants pour se défendre contre les attaques de falsification de requêtes intersites. Vous auriez également probablement besoin de stocker les informations de l'utilisateur dans une base de données qui n'est pas couverte dans cet article.
L'application doit également être servie sur https en production, ce qui peut être fait assez facilement aujourd'hui avec Let's Encrypt.
Bonne OAuthing !