如何创建SSO按钮– Flask登录教程

本文概述

应用程序通常需要登录功能, 以便用户可以保存数据, 创建自己的配置文件, 或者仅仅是为了限制对敏感资源的访问。在现代应用中, 用户希望具有与登录相关的标准功能, 例如电子邮件验证, 密码重置或多因素身份验证。这些功能虽然必要, 但不容易正确使用, 通常也不是应用程序的主要业务。

在用户方面, 他们可能不想经过冗长的注册过程, 因为他们需要创建并记住另一个电子邮件和密码对。如果没有适当的密码管理器, 则用户往往会重复使用相同的密码, 这在安全性方面很糟糕。

发明了单点登录(SSO)(通常被用户称为使用社交媒体按钮登录)作为解决此问题的方法。对于用户来说, 不经历另一个痛苦的注册过程很容易。对于企业而言, 消除用户的摩擦始终是一个巨大的胜利-对于开发人员而言, 所有与登录相关的功能现在都委派给了身份提供商(Facebook, Google, Twitter等), 这意味着更少的代码!你的应用程序仅信任身份提供者执行其验证用户身份的工作。

SSO通常由OpenId Connect(OIDC)或SAML协议提供动力。 SAML通常用于企业应用程序中。 OIDC建立在OAuth2之上, 并被Facebook, Google等社交身份提供商使用。在本文中, 我们将重点介绍OIDC / OAuth2协议。

在此Flask登录教程中, 我们将编写分步指南, 以使用SimpleLogin和Facebook作为身份提供者的SSO登录按钮添加到Flask应用程序中。无需使用任何外部库即可完成此操作, 但是为了简化OAuth的复杂性, 我们将使用Requests-OAuthlib(用于集成OAuth提供程序的库)。如果你有兴趣从头开始实施SSO, 请查看”实施SSO登录” –原始方法。

在本文的结尾, 你应该拥有一个包含以下页面的Flask应用程序:

  • 具有登录按钮的主页
  • 用户信息页面, 成功登录后, 用户将能够看到诸如姓名, 电子邮件和头像之类的信息

该教程的所有代码都可以在flask-social-login-example存储库中找到。

此处也提供了演示。随意在Glitch上重新混合代码。

第1步:Bootstrap Flask应用

安装flask和Requests-OAuthlib。你也可以使用virtualenv或pipenv隔离环境。

pip安装烧瓶requests_oauthlib

创建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上。

使用SimpleLogin登录

步骤2:身分提供者凭证

当前有数百个(如果不是数千个)身份提供者, 其中最受欢迎的是Facebook, Google, GitHub和Instagram。在本篇文章中, 选择SimpleLogin的原因是它易于开发。但是, 相同的代码将适用于任何OAuth2身份提供程序。 (免责声明:我恰好是SimpleLogin的联合创始人, 哎呀, 这可能是我决定使用它的一个因素。)

如果你还没有一个帐户, 请转到SimpleLogin并创建一个帐户, 然后在”开发人员”标签中创建一个新应用。

在应用程序详细信息页面上, 请复制你的AppID和AppSecret并将其保存到变量环境中。在OAuth术语中, 客户端实际上是指第三方应用程序, 即你的应用程序。我们可以将这些值直接放在代码中, 但是将凭据保存到环境变量中是一种很好的做法。这也是”十二个因素”中的第三个因素。

OAuth2设置
export CLIENT_ID={your AppID}
export CLIENT_SECRET={your AppSecret}

在app.py中, 请将这些行添加到文件顶部以获取客户端ID和客户端密码。

import os
CLIENT_ID = os.environ.get("CLIENT_ID")
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")

还要在下一步将要使用的app.py顶部添加这些OAuth URL。它们也可以在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:登录重定向

当用户单击登录按钮时:

  1. 用户将被重定向到身份登录提供者授权页面, 询问用户是否要与你的应用共享他们的信息。
  2. 在用户批准后, 它们将被重定向回你应用程序上的页面, 以及URL中的代码, 你的应用程序将使用该代码来交换访问令牌, 从而使你以后可以从服务提供商处获取用户信息。

因此, 我们需要两条路由:将用户重定向到身份提供者的登录路由, 以及接收代码并将其交换为访问令牌的回调路由。回调路由还负责显示用户信息。

@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上找到。

使用SimpleLogin登录以允许用户信息

用Facebook登录

Facebook, Google和Twitter登录的设置有点复杂, 并且需要其他步骤, 例如设置SSL或选择正确的范围。这些超出了本文的范围。

除了复杂的用户界面外, 集成Facebook最困难的部分可能是找到一种在本地HTTPS上为你的Web应用提供服务的方法, 因为新版本的Facebook SDK不允许使用本地纯HTTP。我建议使用Ngrok(一种免费工具)来获取快速的HTTPS URL。

步骤1:建立Facebook应用程式

请前往https://developers.facebook.com并创建一个新应用:

创建一个新的应用程序ID

然后在下一个屏幕上选择”集成Facebook登录”:

整合Facebook登录

步骤2:Facebook OAuth凭证

单击左侧的”设置/基本”, 然后复制App ID和App Secret。它们实际上是OAuth客户端ID和客户端秘密。

基本设置

更新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 http 5000命令在ngrok后面提供了应用程序, 则需要将当前URL设置为ngrok URL。

# Your ngrok url, obtained after running "ngrok http 5000"
URL = "https://abcdefgh.ngrok.io"

请确保将URL https://abcdefgh.ngrok.io/fb-callback添加到你的Facebook登录/设置, 有效的OAuth重定向URI设置:

有效的OAuth重定向URI

为了访问用户电子邮件, 你需要在范围内添加电子邮件:

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)

回调路线稍微复杂一点, 因为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, i.e. 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登录流程

完整代码在facebook.py上。

总结

恭喜, 你已成功将SSO登录集成到Flask应用中!

为了简单起见, 本教程没有提及其他OAuth概念, 例如范围和状态, 它们对于防范跨站点请求伪造攻击非常重要。你可能还需要将用户信息存储在本文未涉及的数据库中。

该应用还需要在生产时通过https进行投放, 而今天通过Let’s Encrypt可以轻松完成。

OAuthing快乐!

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?