كيفية إنشاء زر SSO - برنامج تعليمي لتسجيل الدخول إلى Flask
نشرت: 2022-03-11غالبًا ما تحتاج التطبيقات إلى وظيفة تسجيل الدخول حتى يتمكن المستخدمون من حفظ البيانات أو إنشاء ملفات التعريف الخاصة بهم أو ربما فقط لتقييد الوصول إلى الموارد الحساسة. في التطبيق الحديث ، يتوقع المستخدمون أن يكون لديهم ميزات قياسية متعلقة بتسجيل الدخول مثل التحقق من البريد الإلكتروني أو إعادة تعيين كلمة المرور أو المصادقة متعددة العوامل. على الرغم من ضرورة هذه الميزات ، إلا أنه ليس من السهل الحصول عليها بشكل صحيح ، وعادة لا تكون النشاط التجاري الرئيسي للتطبيق.
من جانب المستخدم ، قد لا يرغبون في متابعة عملية التسجيل المطولة إما لأنهم يحتاجون إلى إنشاء وتذكر زوج آخر من البريد الإلكتروني وكلمة المرور. بدون مدير كلمات مرور مناسب ، يميل المستخدمون إلى إعادة استخدام نفس كلمة المرور وهو أمر مروع من حيث الأمان.
تم اختراع تسجيل الدخول الأحادي (SSO) ، المعروف في الغالب للمستخدمين باسم تسجيل الدخول باستخدام أزرار الوسائط الاجتماعية ، كحل لهذه المشكلة. بالنسبة للمستخدمين ، كان عدم الخضوع لعملية تسجيل مؤلمة أخرى أمرًا سهلاً. بالنسبة للشركات ، يعد التخلص من الاحتكاك بين المستخدمين دائمًا مكسبًا كبيرًا - وبالنسبة للمطورين ، يتم الآن تفويض جميع الميزات المتعلقة بتسجيل الدخول إلى مزود الهوية (Facebook و Google و Twitter وما إلى ذلك) ، مما يعني رمزًا أقل! يثق تطبيقك ببساطة في مزود الهوية الذي يقوم بعمله المتمثل في التحقق من هوية المستخدم.
عادةً ما يتم تشغيل الدخول المُوحَّد (SSO) بواسطة OpenId Connect (OIDC) أو بروتوكول SAML. يستخدم SAML في الغالب في تطبيقات المؤسسة. تم إنشاء OIDC فوق OAuth2 ويستخدمه موفرو الهوية الاجتماعية مثل Facebook و Google وما إلى ذلك. في هذا المنشور ، سنركز على بروتوكول OIDC / OAuth2.
في هذا البرنامج التعليمي لتسجيل الدخول إلى Flask ، سنكتب دليلًا تفصيليًا لإضافة زر تسجيل دخول SSO إلى تطبيق Flask مع SimpleLogin و Facebook كموفر الهوية. يمكن القيام بذلك دون استخدام أي مكتبة خارجية ، ولكن من أجل تبسيط تعقيدات OAuth ، سنستخدم Orders-OAuthlib ، وهي مكتبة لدمج موفري OAuth. إذا كنت مهتمًا بتطبيق SSO من البداية ، فالرجاء مراجعة تنفيذ تسجيل الدخول الموحد SSO - الطريقة الأولية .
في نهاية هذه المقالة ، يجب أن يكون لديك تطبيق Flask يحتوي على الصفحات التالية:
- الصفحة الرئيسية تتميز بأزرار تسجيل الدخول
- صفحة معلومات المستخدم حيث ، عند تسجيل الدخول بنجاح ، سيتمكن المستخدم من رؤية معلومات مثل الاسم والبريد الإلكتروني والصورة الرمزية
يمكن العثور على جميع الأكواد الخاصة بهذا البرنامج التعليمي في مستودع مثال flask-social-login-example.
يتوفر أيضًا عرض تجريبي هنا. لا تتردد في إعادة خلط الكود على Glitch.
الخطوة 1: تطبيق Bootstrap Flask
تثبيت flask
و Requests-OAuthlib
. يمكنك أيضًا استخدام virtualenv
أو pipenv
لعزل البيئة.
طلبات تثبيت القارورة
قم app.py
الذي يعرض زر تسجيل الدخول على الصفحة الرئيسية:
import flask app = flask.Flask(__name__) @app.route("/") def index(): return """ <a href="/login">Login</a> """ if __name__ == '__main__': app.run(debug=True)
لنقم بتشغيل هذا التطبيق والتحقق من أن كل شيء يعمل بشكل جيد:
python app.py
يجب أن تشاهد هذه الصفحة عند فتح http: // localhost: 5000. الكود الكامل موجود على step1.py.
الخطوة 2: اعتماد موفر الهوية
يوجد حاليًا المئات (إن لم يكن الآلاف) من موفري الهوية ومن أشهرهم Facebook و Google و GitHub و Instagram. بالنسبة لهذا المنشور ، تم اختيار SimpleLogin نظرًا لملاءمته مع المطورين. ومع ذلك ، سيعمل نفس الرمز مع أي موفر هوية OAuth2. (إخلاء المسؤولية: لقد كنت أحد مؤسسي SimpleLogin ، والذي - مهم - ربما كان عاملاً في قراري باستخدامه.)
يرجى التوجه إلى SimpleLogin وإنشاء حساب إذا لم يكن لديك حساب بالفعل ، ثم قم بإنشاء تطبيق جديد في علامة التبويب Developer.
في صفحة تفاصيل التطبيق ، يرجى نسخ معرف التطبيق و AppSecret وحفظهما في بيئة المتغير. في مصطلحات OAuth ، يعني العميل في الواقع تطبيقًا تابعًا لجهة خارجية ، أي تطبيقك. يمكننا وضع هذه القيم مباشرة في الكود ولكن من الممارسات الجيدة حفظ بيانات الاعتماد في متغيرات البيئة. هذا أيضًا هو العامل الثالث في The Twelve Factors.
export CLIENT_ID={your AppID} export CLIENT_SECRET={your AppSecret}
في app.py
، يرجى إضافة هذه الأسطر أعلى الملف للحصول على client id
client secret
.
import os CLIENT_ID = os.environ.get("CLIENT_ID") CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
يرجى أيضًا إضافة عناوين OAuth URL هذه أعلى app.py
والتي سيتم استخدامها في الخطوة التالية. يمكن أيضًا نسخها في صفحة نقاط نهاية 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"
نظرًا لأننا لا نريد أن نقلق بشأن إعداد SSL الآن ، Requests-OAuthlib
أنه لا بأس من استخدام HTTP العادي:
# This allows us to use a plain HTTP callback os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
كالعادة ، يكون رمز هذه الخطوة في step2.py.
الخطوة 3: إعادة توجيه تسجيل الدخول
عندما ينقر المستخدم على زر تسجيل الدخول:
- ستتم إعادة توجيه المستخدم إلى صفحة ترخيص موفر تسجيل الدخول للهوية تسأل عما إذا كان المستخدم يريد مشاركة معلوماته مع تطبيقك.
- بناءً على موافقة المستخدم ، ستتم إعادة توجيههم مرة أخرى إلى صفحة في التطبيق الخاص بك مع
code
في عنوان URL الذي سيستخدمه تطبيقك للتبادل للحصول علىaccess token
يسمح لك لاحقًا بالحصول على معلومات المستخدم من مزود الخدمة.
لذلك نحتاج إلى مسارين: مسار login
الذي يعيد توجيه المستخدم إلى مزود الهوية ومسار callback
الذي يتلقى code
ويتبادله برمز access token
. مسار رد الاتصال مسؤول أيضًا عن عرض معلومات المستخدم.
@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> """
يجب أن يؤدي النقر فوق زر تسجيل الدخول إلى التدفق التالي. يمكن العثور على الكود الكامل على GitHub في step3.py.

تسجيل الدخول باستخدام الفيسبوك
يعد إعداد تسجيل الدخول إلى Facebook و Google و Twitter معقدًا بعض الشيء ويتطلب خطوات إضافية مثل إعداد SSL أو اختيار النطاقات الصحيحة. هذه خارج نطاق هذا المقال.
بصرف النظر عن واجهة المستخدم المعقدة ، قد يكون الجزء الأصعب في دمج Facebook هو إيجاد طريقة لخدمة تطبيق الويب الخاص بك على HTTPS محليًا لأن الإصدار الجديد من Facebook SDK لا يسمح بـ HTTP المحلي العادي. أوصي باستخدام Ngrok ، وهي أداة مجانية للحصول على عنوان URL سريع لبروتوكول HTTPS.
الخطوة 1: قم بإنشاء تطبيق Facebook
يرجى التوجه إلى https://developers.facebook.com
وإنشاء تطبيق جديد:
ثم اختر "دمج تسجيل الدخول إلى Facebook" في الشاشة التالية:
الخطوة 2: بيانات اعتماد Facebook OAuth
انقر فوق "الإعدادات / الأساسي" على اليسار ، وانسخ معرف التطبيق وسر التطبيق . إنها في الواقع client-id
OAuth client-secret
.
قم بتحديث client-id
client-secret
.
export FB_CLIENT_ID={your facebook AppId} export FB_CLIENT_SECRET={your facebook AppSecret}
تحديث AUTHORIZATION_BASE_URL و TOKEN_URL:
FB_AUTHORIZATION_BASE_URL = "https://www.facebook.com/dialog/oauth" FB_TOKEN_URL = "https://graph.facebook.com/oauth/access_token"
الصفحة الرئيسية:
@app.route("/") def index(): return """ <a href="/fb-login">Login with Facebook</a> """
الخطوة 3: تسجيل الدخول ونقاط نهاية رد الاتصال
إذا تم تقديم التطبيق خلف ngrok
باستخدام الأمر ngrok http 5000
، فنحن بحاجة إلى تعيين عنوان URL الحالي على عنوان URL الخاص بـ ngrok.
# Your ngrok url, obtained after running "ngrok http 5000" URL = "https://abcdefgh.ngrok.io"
يرجى التأكد من إضافة عنوان url إلى إعدادات / تسجيل الدخول إلى Facebook ، وإعداد OAuth Redirect URIs الصحيح:
من أجل الوصول إلى بريد إلكتروني للمستخدم ، تحتاج إلى إضافة email
إلى 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)
يعد مسار callback
أكثر تعقيدًا بعض الشيء حيث يتطلب Facebook إصلاح الامتثال:
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> """
الآن عند النقر فوق تسجيل الدخول باستخدام Facebook ، يجب أن تكون قادرًا على متابعة التدفق بالكامل.
الكود الكامل موجود على facebook.py.
خاتمة
تهانينا ، لقد نجحت في دمج تسجيل الدخول الموحّد (SSO) في تطبيق Flask!
من أجل البساطة ، لا يذكر هذا البرنامج التعليمي مفاهيم OAuth الأخرى مثل النطاق والحالة ، والتي تعتبر مهمة للدفاع ضد هجمات التزوير عبر المواقع. قد تحتاج أيضًا إلى تخزين معلومات المستخدم في قاعدة بيانات لم يتم تناولها في هذه المقالة.
يجب أيضًا تقديم التطبيق على https عند الإنتاج ، والذي يمكن تنفيذه بسهولة اليوم باستخدام Let's Encrypt.
OAuthing سعيد!