什么是 OAuth 2.0 ?
OAuth(Open Authorization)是用于授权的开放的网络协议,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。当然,它本身也可归属为安全协议的范畴,在实际应用的时候就是保护互联网中不断增长的大量 Web Resources 的安全性。
OAuth 2.0 是一个关于授权(Authorization)的开放网络标准协议,是OAuth协议的下一版本,但不向下兼容OAuth 1.0(即完全废止了OAuth1.0)。OAuth 2.0关注客户端开发者的简易性,同时为Web应用、桌面应用、手机和智能设备提供专门的认证流程。
这儿需要注意的是 Authorization(授权),而不是 Authentication (认证)。用来做 Authentication(认证)的标准协议叫 OIDC(OpenID Connect),我们下个章节会详细讲解。
OK,到这儿可能有朋友要问,我们问什么要用 OAuth 2.0 协议呢?
为什么要用 OAuth 2.0 ?
在传统的授权领域中,客户端请求访问受限制的资源(系统内部受保护资源)时,服务端会通过使用资源所有者的服务器进行身份验证,以便为第三方应用程序提供访问权限,资源所有者与第三方共享授权凭证。这种方式无疑会造成下面几种问题:
- 第三方应用程序需要存储资源所有者的授权凭证以供将来使用,而这个凭证通常是明文密码。
- 尽管使用密码存在这种安全缺陷,但服务器仍然需要支持密码身份验证。
- 第三方应用程序可以直接获得对资源所有者的受保护资源的所有权,但资源所有者却无法对具体的资源或者资源集合做过于精细化的访问控制。
- 如上,资源所有者如果想撤销第三方应用程序对某个资源的访问权限,只能将第三方应用程序的权限全部收回,或者重新编码实现。
- 极其容易因为第三方用户密码泄露导致资源服务器上受保护资源的大批量泄露。
OAuth 通过在第三方应用与服务提供商之间引入了一个授权层来解决这些问题。首先就要求第三方应用不能直接登录服务提供商,只能先登录授权层,获取到授权层颁发的访问令牌(Access Token:一串包含具体的资源权限、有效期和其他授权相关属性的字符串)。只有通过这个令牌,才能获取到相应权限的资源(并非全部资源),以此将第三方应用与服务提供商区分开。
OAuth 2.0 包含哪些角色?
想使用 OAuth 2.0 授权,就必须先了解它具备哪些角色。
- Resource Owner 资源所有者,即代表授权客户端访问资源信息的用户
- Resource Server 资源服务器,托管受保护的用户信息
- Authorization Server 授权服务器,验证用户身份然后为客户端颁发资源访问令牌
- Resource Server 和 Authorization Server 可以是同一台服务器,也可以是不同的服务器,视具体的授权平台而有所差异
- Client 客户端,即代表意图访问受限资源的第三方应用
OAuth 2.0 包含哪些授权方式?
授权码模式(Authorization Code)
这种方式是最常用的流程,也是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样可以避免令牌泄漏。
简化模式(Implicit)
这种方式不通过第三方应用程序的服务器,RFC 6749 就规定了这种方式方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit),一般移动 APP 端多选用这种方式。该模式一般用于 APP 端授权。
密码模式(Resource Owner Password Credentials)
用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。该模式可以用于 APP 端授权(不建议)。
客户端模式(Client Credentials)
指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。
OAuth 2.0 的授权流程是什么?
针对每种授权方式,OAuth 2.0 都有相对应的授权流程,这儿仅对使用最广泛的“授权码模式”的流程进行讲解。
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
我们对照上面讲到的授权角色,逐步分解以上流程:
- A - 用户(Resource Owner)通过浏览器(User-Agent)中客户端(Client)提供的授权连接(包含客户端身份信息(Client Identifier)和授权成功后的回调地址(Redirection URI)等信息)访问授权服务器(Authorization Server)。
- B - 授权服务器(Authorization Server)对用户(Resource Owner)进行身份验证,并确定用户(Resource Owner)是授予还是拒绝了客户端的访问请求(指用户在第三方授权页面是否登录成功后点击了“同意授权”按钮)。
- C - 假设用户(Resource Owner)授予访问权,授权服务器(Authorization Server)使用先前提供的回调地址(Redirection URI)将用户代理重定向回客户端(Client)。重定向 URI 包括一个授权码和客户端之前提供的 State。
- D - 客户端(Client)通过包含上一步中接收到的授权码和回调地址等参数,向授权服务器(Authorization Server)的申请访问令牌(Access Token)。
- E - 授权服务器(Authorization Server)对客户端(Client)进行身份验证,验证授权码,并确保接收到的重定向 URI 与步骤(C)中用于重定向客户端的 URI 相匹配。如果有效,授权服务器将返回访问令牌(Access Token)和刷新令牌(Refresh Token,该返回值非必须)。
如果以上流程难于理解,下面我们可以换一种方式,直接通过实际案例演示这个流程。
首先我们引入三个角色(实际是四个,Resource Server 和 Authorization Server 相同):
- 用户A:可以理解成你自己,对应“Resource Owner”角色
- 网站B:可以理解成 OSChina,对应“Client”角色
- 第三方C:可以理解成 Github,对应“Resource Server”和“Authorization Server”角色
需求:你(用户A)想通过 Github(第三方C) 登录网站B(OSChina)。
具体流程如下:

参考资料