您需要了解的关于OAuth的所有信息(2.0)

2020-07-16 05:41:46

现代人可能在几十个应用程序上都有个人资料。无论是社交媒体应用程序、音乐/视频流还是工作空间资源,我们每个人都必须管理包含个人信息的帐户。随着时间的推移,这些孤立的应用程序之间的联系越来越紧密。Twitter允许新闻网站直接发推文,Discorde在Facebook上搜索推荐的朋友,Jira使用Github个人资料创建用户账户。这种允许应用程序代表您相互对话的趋势被称为“委托访问”,并且已经成为我们在线生活中必不可少的一部分。

然而,由于这些应用程序保护其数据的方式,开发人员遇到了一个挑战:我们如何委派访问权限?几乎每个应用程序都受到基本用户名/密码模式的保护。要允许应用程序A从应用程序B访问它需要的数据,需要经常代表应用程序A登录到应用程序B-这是多么笨拙!解决方法是为应用程序A提供登录到应用程序B的用户名和密码凭据,这是有问题的,原因如下:

OAuth的形成是为了解决这种进退两难的情况:如何在不危及最终用户数据的情况下提供委托访问。

它有助于理解有关协议的常见术语。注意:就本文而言,OAuth指的是OAuth 2.0,这是自2012年以来的最新版本。

客户端:希望访问资源服务器并代表资源所有者执行操作的应用程序。

授权服务器:知道资源所有者并可以授权客户端访问资源服务器的服务器。

归根结底,OAuth的存在是为了在不损害用户数据的情况下为第三方应用程序提供对安全资源的有限访问。考虑到特斯拉有一个“代客模式”,您需要一个代客钥匙卡。这张钥匙卡通知车辆,它将以有限的功能操作,限制最大速度和加速度,并锁定后备箱。此技术在概念上与OAuth的操作方式相同。特斯拉车主让贴身男仆有限地进入他/她的特斯拉,而不需要提供主车钥匙。

OAuth在社交媒体应用中相当受欢迎。您可能熟悉这样的请求:

图1:使用OAuth,Spotify(客户端)能够代表Bob(资源所有者)在没有凭据的情况下访问Facebook(资源服务器)。

当接收到这样的弹出窗口时,OAuth协议在后台运行如下:

Spotify向Bob发送一条消息,请求获得访问他的公共资料、朋友列表、电子邮件和生日的权限。

Facebook API验证授权并为Spotify发送访问令牌以访问受保护的资源。

通过使用奖励和令牌(我们将在下面讨论),Spotify将获得Bob的代客卡到他的Facebook账户。

上面的部分提供了50,000英尺的OAuth工作原理视图。现在,让我们来看看引擎盖下的情况,看看使协议能够正常工作的部分。

在上一节中,我们讨论了OAuth的抽象设计-客户端、资源所有者、授权/资源服务器。在这个系统中,还包括:

作用域和令牌是OAuth实现精细访问控制的方式。它们一起代表了“做某事的许可”。令牌是“权限”部分,作用域定义了什么是“做某事”。想一想电影票:范围是您被授权观看的电影的名称,而电影票本身是令牌,只有影院员工才能验证它是真实的。在我们的特斯拉示例中,范围是使用代客键启动时启用哪些车辆功能。访问令牌是代客钥匙本身,只有当钥匙由特斯拉经销商发放时,特斯拉车辆才能识别。

回到图2,我们可以看到授权服务器具有与资源服务器不同的API。从功能上讲,授权服务器用于验证和授权客户端,而资源服务器承载所请求的资源。为了让资源服务器知道是否接受信息查询,它必须知道请求者是否已被授权。这就是访问令牌的用武之地;它的存在是为了通知资源服务器请求者已经经过授权服务器的审查,并且有权进行查询。通过使用令牌作为代理,抽象了提供凭据的需要。接入令牌通常作为JWT承载令牌发布。这些令牌经过加密签名,对客户端没有意义,但是当由资源服务器解码时,它们包含重要信息。访问令牌中包含的变量之一是其作用域。

因为作用域限制了可以做的事情,所以它们本身必须由资源(如Facebook)定义。通常,有四种类型的作用域:

作用域可以得到一些东西,做一些事情,两者兼而有之,或者两者都不做。上面的Facebook和Spotify示例是一个读权限的实例,而路透社请求在tweet上发布一篇文章则是写权限。定义作用域是指定如何允许第三方访问用户数据的极其强大的工具。要了解如何使用作用域,请尝试阅读Slake和Google等公司的文档,这些公司都演示了作用域参数的不同排列。

还有另一种类型的令牌,称为刷新令牌。它们不是访问资源的“键”,而是用于在它们不再起作用时自动获得新的访问令牌(例如,已过期)。像Facebook这样的应用程序可以通过强制使用可选刷新令牌来定期验证授权,以获得新的访问令牌,从而实现更高程度的安全性。刷新令牌有一个重要功能:可以通过使其无效并返回客户端对特权资源的访问来撤销它们。

授权规定了客户端获取访问令牌的操作顺序。这些独特的顺序称为流。回到我们电影院的类比,有两种方式可以获得门票:(1)在电影院购买(2)在线购买。您选择的方法决定了您将如何获得门票。在大区购买可能如下所示:

正如您所看到的,授权并不像令牌那样是重要的东西,而是指示要使用哪个流。我们已经介绍了一种类型的授权刷新令牌(参见图3)。不同的授权针对特定的使用情形进行了优化,并将影响最终用户与客户端应用程序的交互方式以及所应用的安全措施。理解构成每种赠款类型的不同参数很重要,但这将使本文变成一篇短篇小说。相反,在下面的Github研究中,我们将重点介绍最常见的授权类型:授权码授权。

回想一下,OAuth在HTTPS上工作。资源所有者、客户端和授权服务器之间的所有通信都通过URI进行。这些URI是包含作为字符串一部分的参数的查询。这些参数中包含授权服务器需要了解要遵循哪个流的信息。在这一点上,重要的是要注意,有两种类型的客户端:机密客户端和公开客户端。可以信任机密客户端安全地持有令牌,这是访问资源所必需的。这样的客户端可以包括服务器端应用程序。不能信任公共客户端存储客户端凭据。这些类型的客户端包括移动或Javascript浏览器应用程序。

授权码授权__-授权码授权可能是最常见的授权类型(参见图4)。本质上,客户端接收授权服务器发出的唯一代码,然后将其交换为令牌。通过将接收令牌所需的步骤分解为两个不同的查询,授权服务器能够在颁发令牌之前验证有关客户端的重要信息。

带PKCE扩展的授权码授权-此授权码授权变体用于无法信任存储凭据的公共客户端。使用PKCE扩展(代码交换公钥),客户端和服务器传输散列以验证通信未被截获。

客户端凭据-在某些情况下,客户端请求的是自己的访问权限,而不是资源所有者的访问权限。这些实例发生在机器之间,例如需要访问云存储的任何后端服务。在这种情况下,客户端将发出一个请求,该请求将包括参数‘client_id’和‘client_ret’,授权服务器可以验证这些参数以颁发访问令牌。此类型的授权应仅用于机密客户端,并且必须首先注册。

设备代码-此授权扩展适用于没有浏览器或键盘体验糟糕的联网设备,如使用控制器和虚拟键盘登录游戏机。如果您已将智能电视连接到您的视频流帐户,则您可能已经使用过此流。

把所有这些概念放在一起,我们可以进行一个案例研究。Teleport是一款开源远程访问工具,允许用户使用OAuth通过Github单点登录(SSO)进行登录。让我们看看怎么做!

我们准备好出发了!如上所述,我们将遵循授权码授予。这是因为令牌所有者是用户,而客户端是服务器端应用程序。远程端口不是托管的,所以让我们假设我们已经在您的基础设施中安全地安装了它。如果没有,则应使用PKCE扩展。

远程端口用户单击“登录”,并使用HTTPS GET请求中包含的以下参数进行重定向:

AUTHORIZATION_SERVER是GAS公开的URL。所有资源应用程序都将提供可重定向到的URL,通常是API。对于吉瑟布,这是https://github.com/login/oauth/authorize。

client_id为GAS提供一个字符串,它可以根据授权客户端的注册表检查该字符串。像Github这样的应用程序将需要注册客户端以帮助识别它们。我们使用12345作为ID。

redirect_uri用Teleport需要的所有变量通知GAS将Teleport用户定向回哪个URL。对于本例,我们可以将重力文档中提供的示例重定向URL作为https://teleport.example.com:3080/v1/webapi/github/callback。

范围定义了访问资源的限制。这些作用域由资源应用程序在内部定义。我们可以在这里看到吉瑟布的望远镜。查看Teleport的repo时,我们发现惟一需要的范围是Read:org,它允许Teleport读取组织成员、团队成员和组织项目。

state是由Teleport随机生成并与授权服务器来回传递的字符串。通过传递此字符串,客户端和授权服务器都知道它们在通信之间与同一设备通话。在本例中,假设州字符串是Syl(我的狗的名字)。

综合所有这些参数,远程端口用户在接受登录提示后被定向到的URI将如下所示:

一旦GAS接收到查询,它将对照远程端口的注册表验证client_id。知道Teleport正在等待授权码后,GAS会将用户带着传递的代码和状态参数发送回重定向URL。我们的下一站是:

收到代码后,Teleport会自动查询GAS,以换取包含code、redirect_uri和client_id参数的令牌。提供了两个附加参数:

CLIENT_SECRET来自客户端注册过程中的Github。此字符串应该是秘密的,不能公开访问。因为Teleport托管在我们自己的基础设施上,我们知道这些基础设施是安全的,所以我们可以放心地传递此参数。否则,我们将使用PKCE扩展并散列生成的字符串。在这种情况下,我们的秘密是引力。

回想一下,将代码交换为令牌需要POST请求。综上所述,Teleport现在发送一个查询:

使用CLIENT_SECRET和代码,授权服务器能够验证Teleport客户端的请求,并发出自编码的JWT承载令牌,该令牌带有范围和过期时间(可以包括刷新令牌)。这样的令牌可能如下所示:

{“ACCESS_TOKEN”:“IEZKr6ePPtxZBED”,“TOKEN_TYPE”:“承载”“范围”:“Read:org”,“Expires_In”:3600}。

现在我们已经获得了访问令牌,剩下的就是代表Teleport用户发出API请求并接收所需的资源。我们通过在HTTPS授权头中将访问令牌作为承载凭证传递来实现这一点。回想一下,我们的作用域是Read:org,这意味着我们可以成功调用的方法很少。考虑到这一点,我们的标题可能类似于:

成功!如果你已经走到这一步,恭喜你!尽管OAuth提供了一个经常被忽视的便利,但它是一个复杂的协议,需要时间来实现。我们刚刚介绍的示例是OAuth流可能的一百种排列之一。此时,我希望您对该协议有一个全面而充分的概念性理解,以便您能够轻松地自己探索该协议。