Comment créer un bouton SSO - Un tutoriel de connexion Flask

Publié: 2022-03-11

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

Connectez-vous avec SimpleLogin

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

Paramètres OAuth2

 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 :

  1. 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.
  2. 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 un access 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.

Connectez-vous avec SimpleLogin pour autoriser les informations utilisateur

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 :

Créer un nouvel ID d'application

Choisissez ensuite « Intégrer Facebook Login » sur l'écran suivant :

Intégrer la connexion Facebook

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

Paramètres de base

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 :

URI de redirection OAuth valides

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.

Connexion avec le processus Facebook

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 !