OAuth 是 Open Authorization 的缩写, 顾名思义 OAuth 是一个开放授权协议, 截止目前使用最广泛的协议版本为 OAuth 2.0, 其协议标准文档为 RFC 6749, OAuth 在我们日常使用的软件和系统中经常用到, 例如我们在微信小程序中注册账号时通常会弹出 "xxx 申请使用您的手机号码", 我们可以选择允许或拒绝, 这便是一种 OAuth 授权, 再例如在一些 app 中绑定社交账号, 例如绑定微博, 通常会跳转到微博的授权页, 话术比如为 "xxx 申请访问您的微博好友关系", 这也是一种 OAuth 授权, 这些都是 OAuth 在日常软件中的应用 (当然这些应用的实现不一定完全 100% 地遵循 OAuth 协议), 更标准地, 例如我们要使用 Github 的 API, 首先需要申请 Access Token, 在申请 Access Token 的时候会选择 Access Token 所具有的权限, 如 CreateRepo, CreateIssue 等等, 这是一个非常标准的 OAuth 授权, 本文完整讨论 OAuth 2.0 的协议设计

OAuth 协议概述

OAuth 协议是针对 HTTP 服务而设计的 (当然在实际应用中其设计思路也可以用于其它协议之上, 但这已不在 OAuth 标准的范畴之内), 在 HTTP 服务中通常会有一些受保护的敏感资源, 例如我们可以创建一个存放个人私密文件的 HTTP 服务, 要访问给该服务则首先需要通过认证 (例如用户名-密码的方式), 如果我们需要允许第三方应用程序访问这个服务, 在 OAuth 协议之前, 我们的做法只能是将自己的用户名和密码分享给第三方服务以便通过服务的认证, 这样会有以下几点问题:

  1. 用户名和密码给到第三方应用程序, 第三方应用程序在掌握了这些信息之后实际上是可以不受限制地访问所有隐私资源, 即这种方式无法限定第三方应用程序的权限范围
  2. 这种方式没有限定第三方应用程序的授权时间, 只要用户名和密码没有变更, 则第三方应用程序可以持续地访问敏感资源
  3. 当我们将隐私服务授权给多个第三方应用程序后, 无法单独撤销对某一个第三方应用程序的授权, 因为要撤销授权只有修改用户名和密码, 而一旦修改用户名及密码, 所有使用该用户名及密码的第三方应用程序都将无法继续访问敏感服务

实际上我们仔细分析以上 3 条会发现问题的本质出在认证这一环节上, 在传统方式下, 认证环节没有区分请求认证的一方是第三方应用程序还是服务的 Owner, 即认证时只校验用户名和密码, 谁拥有了用户名和密码谁就可以访问敏感资源, OAuth 协议可以妥善地解决上面的问题, 它引入了一个单独的认证层, 并对第三方应用程序和服务 Owner 的角色做了划分, 在 OAuth 协议下, 第三方应用程序将在服务 Owner 的限制和管控下访问拥有权限的特定敏感资源, 并且授权本身具有时间期限, 此外服务 Owner 也可以随时撤销对某个第三方访问的授权, 在 OAuth 协议中共有 4 个主体, 分别是资源所有者 (即 Resource Owner)、资源服务器 (Resource Server)、认证服务器 (Authorization Server) 以及第三方应用程序 (我们统一称为 Client), 每个主体的作用和职责如下:

  1. 资源所有者 (Resource Owner) 顾名思义是资源的拥有者, 它拥有对资源绝对的访问权限
  2. 资源服务器 (Resource Server) 用于存放敏感资源
  3. 认证服务器 (Authorization Server) 在资源所有者的控制之下, 向请求访问敏感资源的第三方应用 (Client) 颁发 Access Token, 认证、校验请求访问敏感资源的请求方, 维护请求方的权限边界、授权时长等授权信息
  4. 第三方应用程序 (Client) 即期望访问敏感资源的应用程序, 它在获得授权后, 在授权期限内可向资源服务器请求访问特定的(被授权的) 敏感资源

OAuth 协议标准本身不限定资源服务器 (Resource Server) 和认证服务器 (Authorization Server) 的交互方式, 在具体实现中它们可以是同一个实际 Server, 也可以是不同的 Server, 并且一个认证服务器在实现上并不限定其只能颁发针对某一个资源服务器的 Access Token, 它可以同时为多个资源服务器服务

OAuth 2.0 协议的抽象交互流程图如上所示, Client 想要访问 Resource Server 上的某些敏感数据, 它首先向资源所有者 Resource Owner 发起申请, Owner 审批通过后给予其一个认证凭证, 这个凭证不是访问最终敏感数据的凭证, 而是向认证服务器 Authorization Server 申请 Access Token 时所需要提供的凭证 (Client 也可以直接向认证服务器发起请求, 由认证服务器作为中介向资源所有者申请授权, 下面讨论协议细节时会分情况展开说明), 认证服务器校验、检查 Client 提供的凭证, 根据该凭证认证服务器可以知晓 Client 的请求已经经过了资源所有者的授权, 并且该凭证也包含了相应的如授权时长, 授权范围等授权属性信息, 认证服务器校验没有问题之后向 Client 颁发 Access Token, 根据资源所有者授予的凭证中包含的信息设置 Access Token 的如过期时间, 访问限制范围等属性, 最后 Client 在取得 Access Token 之后便可以向资源服务器发起请求以访问受保护资源