1. 简介

1.1. 什么是授权

试想像有一座房子,里头有无数房间。而你作为这座房子的管家,拥有一把万能钥匙,可以打开房子内所有的门。 此外,这把万能钥匙还有一个作用,就是产生出开启特定门的钥匙。 你可以将新产生出的钥匙交给其他人,其他人就可以自由进出特定房间。这个动作就是「授权」。

1.2. 什么是 OAuth

OAuth 是一个开放标准的授权协议 ,它允许软件应用代表(而不是充当)资源拥有者去访问资源拥有者的资源。应用向资源拥有者请求授权,然后取得令牌(token),并用它来访问资源。这一切都不需要应用去充当资源拥有者的身份,因为令牌明确表示了被授予的访问权。

众所周知,OAuth是一个安全协议,协议规范是这样定义的:

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.2

OAuth 2.0 框架能让第三方应用以有限的权限访问 HTTP 服务,可以透过构建资源拥有者与 HTTP 服务间的许可交互机制,让第三方应用代表资源拥有者访问服务,或者通过授予权限给第三方应用,让其代表自己访问服务。

作为一个 授权框架 ,OAuth关注的是如何让一个系统组件获取对另一个系统组件的访问权限。我们需要关心如下组件:

  • 资源拥有者 能将访问授权委托出去。资源拥有者指的是用户本身,或在系统中的账号。起初的 OAuth 设计是基于HTTP的,所以可以理解为坐在浏览器前的人。或是举的例子–房子的管家–。将访问授权委托出去的过程,就是利用万能钥匙产生出其他有限钥匙并转交他人的过程。
  • 某种受保护资源 。 OAuth 并不关心受保护资源长什么样子,可能是个 RESTfule API、某个页面、URI 所识别的其他种类资源。 就像是宅邸里每一个房间。
  • 客户端 。 客户端指的就是代表资源拥有者访问受保护资源的软件。 也就是将产生出的钥匙转交给「他人」。

1.3. OAuth 不是什么?

  • OAuth 不是身份验证协议 。虽然可以基于 OAuth 进行身份验证。但其关注的重点仍在授权而非身份验证。
  • OAuth 没有定义用户对用户的授权机制 。同样不是不行,但它根本上是一个用户向应用软件授权的协议。它甚至不关注访问控制。
  • OAuth 没有定义授权处理机制。虽然 OAuth 定义了一些授权框架/流程,但不定义授权的内容。相反,由服务API定义用户许可证范围,允许令牌适合哪些操作。
  • OAuth 没有定义令牌格式。OAuth 协议明确申明了令牌的内容对于客户端是完全不透明的。虽然令牌本身对于客户端是不透明的,但接受令牌处理的服务,仍然需要理解令牌。 换句话说授权服务器产生令牌,但对于令牌的理解全依赖于资源服务器。
    • 同本节的例子,万能钥匙产生了新的房门钥匙。但这把钥匙实际能不能够使用,由门锁直接决定。与拿到钥匙的人、管家没有直接关系。
  • OAuth 2.0 没有定义加密方法。尽管为了安全,诸多服务如 Google、Spofit y都会要求客户端支持 HTTPS。但框架本身同样不关注这部分,也不管令牌如何签名、加密、验证。
  • OAuth 2.0 不是单体协议。从上述来看,该规范被分成多个定义和流程,每个定义和流程都有各自适用的场景。

OAuth 2.0 规范定义了一个授权协议,用户在 Web 应用以及 API之 间传递授权决策。因为 OAuth 2.0 用于获取已经通过身份验证的最终用户的许可,所以很多开发人员和API服务商认为 OAuth 2.0 是一种让用户安全登入的身份认证协议。然后,尽管 OAuth 2.0 是一个需要用户交互的安全协议,但并不是身份认证协议。

OAuth 2.0 不是身份认证协议。

之所以会产生如此多的误解,是因为 OAuth 2.0 经常被用于身份认证协议内部,而常规的 OAuth 2.0 流程内部也会包含一些身份验证事件。所以,很多开发人员看到这样的 OAuth 2.0 流程,以为使用 OAuth 就是执行身份验证。这种想法不仅是错误的,而且会给服务提供商、开发人员和最终用户带来危险。

1.4. OAuth 1.0

开发人员试图发明一个协议,允许用户将 API 访问授权出去。新的协议基于多个具有同样思想的专有实现,包括 Google 的 AuthSub 以及 Yahoo! 的 BBAuth。在这些实现中,客户端应用只要获得用户的授权并得到一个令牌,就能够使用这个令牌访问远程 API。

这些令牌的发放都包含公共和私有的部份,并且该协议使用了一种新型的(现在看来是脆弱的)加密签名机制,使得它可以在非 TLS HTTP 连接上使用。他们称为这个协议为 OAuth 1.0,并将其作为一项 Web 开放标准发布,它很快获得响应,出现了多种语言对这一标准的自由实现。这一标准表现优秀,深得开发人员喜爱,甚至一些大型网络公司也很快弃用了自己的专有机制,起初正是这些专有机制启发了 OAuth。

– Justin Richer

OAuth 2.0 并不兼容 OAuth 1.0 。但相关概念最早始于2006年11月。现在看到的 OAuth 应该大多都直接是指 OAuth 2.0 。在2009年4月30日。 OAuth 1.0 被发现一个安全漏洞。同样地, OAuth 2.0 可能也不是一个完美的协议,但从现实层面来看,今天的它非常流行,以至于开发者几乎不能不知道。

2. 身份认证与授权

对于一个应用来说,最重要的是它的业务逻辑 。 除了业务逻辑本身,为完成所需的工作,会需要取得必要之资源。这可能是一份档案, 镜头、麦克风资源等不同种形式。

在 取得资源 过程中,也会有另外一层业务逻辑,也可能本身就是另一只程序服务,对所需取得的资源,进行 访问控制 。

最后,为了判断是否具有存取该项资源的权限,有可能有必要进行 身份验证或授权 。

在上面例子,「身份验证/授权服务」可能是身份服务器和授权服务器;「访问控制服务」可能是资源服务器。 但也有不少做法是将身份和授权做在一起,资源访问控制直接由应用(业务逻辑)处理。更甚者,身份验证于应用的不同逻辑层的状况也不少见。

在上面例子,【身份验证/授权服务】可能是身份服务器和授权服务器;【访问控制服务】可能是资源服务器。 但也有不少做法是将身份和授权做在一起,资源访问控制直接由应用(业务逻辑)处理。更甚者,身份验证于应用的不同逻辑层的状况也不少见。

2.1. 身份验证与访问控制

接着,来更仔细的看看身份验证与访问控制内部。这两者都可以想象其内部有一个执行器(executor)。 这个执行器可以根据读取的规则列表(rules list)来判断是否通过身份验证或允许存取资源。

这个执行器可能是执行账号密码检验,规则列表就是每个人的账号密码。 透过读取规则列表找到身份识别的账号,比对与规则列表内的密码,以验证身份。

身份验证并不会只有账号密码这么一种,所以可能会有多个执行器,每个执行器都有他的规则列表。 除了账号密码外,身份私钥验证、一次性密码验证都有可能。

除了可替换的验证方式外,可以改成多增加一个政策输入(Policy)。透过不同的政策,读取不同规则列表,然后执行不同策略。

这里的 Policy 可能与其他像似系统有很大的不同。有可能称之为执行模型(model)或策略(strategy)。不过姑且先称之为 policy。尽管有时 Policy 直接代表者多个规则(rules),更像是规则列表(rules list)。但你可以想象成该清单上还有一段讯息(meta data),记载着如何理解这些规则。

然后访问控制和身份验证很像。有非常多种访问控制的政策可以选择。更甚者你可以将执行器单独来看,并将执行器嵌入到业务应用之中。

2.2. 账号密码代理

比如说你有 qq 的账号,但你更喜欢 Gmail 的界面,所以你希望使用 Gmail 来处理 qq 的信件。这时候其实你就是告诉了 Gmail 关于 qq 的账号密码。相对的,也就是你应该是信任的 Google 的服务。当在使用的服务是同一个提供商时,这种直接使用账号密码的情况就相当正常。他们本就可以共享一些信息,可能使用了相同的内存空间、 使用了相同的数据库等。

应该留意使用的真的是同一个服务,还是其实是一个代理(Proxy)?

当使用代理时,这样的情况,这个代理有可能短暂的持有你的账号密码信息。

2.3. 特殊密码

我们将这个代理,再扩展一些。它或许不只是一般的软件,更是操作系统,乃至硬件。想想,你一般使用私人计算机收信。但偶尔会需要使用公司计算机、公共计算机登入。尽管或许你还是使用 Gmail 的服务, 但实际上这之中通过了好几层代理。

首先,硬件、操作系统上你不知道有没有安装硬件键盘记录器。接着浏览器也同样是一个代理,使用的是可信任的浏览器吗?

那该怎么办?我们可以与服务约定一种「特殊密码」。这种密码只能使用一次,是一次性密码(OTP, One Time Password)。 现在一次性密码更常见到于二阶段验证(双因子验证/2FA, Two Factor Authentication)。但实际上存在非常多种形式:

  • 透过短信验证: 透过短信发送一组限时且只能使用一次的密码
  • 透过邮箱验证: 透过邮件发送一组限时且只能使用一次的密码
  • 特殊连接验证: 透过一个特殊的连接,该连接有时效性,且只能存取一次。
  • 透过时间产生特殊密码: TOTP, Time-base One Time Password。
  • 透过哈希产生特殊密码: HOTP, HMAC-based One Time Password。
  • 与系统服务约定好数组一次性密码
  • 与系统服务约定好特殊状况使用密码
  • 使用移动设备登入

2.4. 开发者令牌

还有一种情况是开发的应用本就是系统服务框架下的一部分,你本身就是开系统的开发人员之一。你已可能有一把非常强大的开发者钥匙(密码或令牌)。 你或许会去验证使用者身份或许不会,但你直接使用这个钥匙来处理服务。

为什么会有这种情况?或许该子服务本身就设计成只有开发者令牌,细部控制并不够精细,所以需要一个看门人(gatekeeper)来检查是否有权限操作服务。

  • 无标签
写评论...