OAuth (Open Authorization, 开放授权), OpenID

创建时间:
2014-02-18 00:10
最近更新:
2018-05-26 17:38

Brief

An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.

The OAuth 2.0 authorization framework enables third-party applications to obtain limited access to a web service.

-- http://oauth.net/

OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 supersedes the work done on the original OAuth protocol created in 2006. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices. This specification and its extensions are being developed within the IETF OAuth Working Group.

-- http://oauth.net/2/

OAuth 是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源 (如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。

OAuth 允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站 (例如,视频编辑网站) 在特定的时段 (例如,接下来的 2 小时内) 内访问特定的资源 (例如仅仅是某一相册中的视频)。这样,OAuth 允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。

OAuth 1.0 复杂、易用性差,没有得到普及。

OAuth 2.0 是 OAuth 协议的下一版本,但不向后兼容 OAuth 1.0。OAuth 2.0 关注客户端开发者的简易性,同时为 Web 应用,桌面应用和手机,和起居室设备提供专门的认证流程。

Official Website

http://oauth.net/
http://oauth.net/2/ - OAuth2.0 协议标准
http://tools.ietf.org/html/rfc6749 - The OAuth 2 Final Specification on IETF (Internet Engineering Task Force)

Resource

  1. OpenID 和 OAuth 有什么区别
  1. 帮你深入理解 OAuth 2.0 协议 - Tony praise
  2. 理解 OAuth 2.0 - 阮一峰
  3. 腾讯 与 新浪微博 的 OAuth 2.0 返回的用户信息
  4. OAuth 2.0 原理和验证流程分析
  1. oAuth 1.0 原理及开发流程
  2. QQ OAuth 1.0 认证中 URL 的调用及参数的传递
  3. 简述 OAuth 2.0 的运作流程
  4. OAuth 2.0 - Authorization Code授权方式详解
  5. Authorization code 与 Implicit 授权案例
  6. Authorization code 与 Implicit 授权案例
  7. 用于成员资格的 ASP.NET OpenAuth (Entrance on MSDN)
  8. 国内各大公司 OAuth 与 API 比较
  9. 淘宝开放平台使用 OAuth
  10. 豆瓣
  11. 人人
  12. Other
  13. Other
  14. Other
  15. Other
  16. Other
  17. Other
  18. Asp.Net MVC 4 Web API 中的安全认证 - 使用OAuth
  19. ASP.NET MVC 4 使用 OAuth
  20. ***
  21. ***
  22. *** (zh-CN)
  23. *** (en-US)
  24. ***
  25. 翻译:WebApi 认证--用户认证Oauth解析
  26. Web Api2 用户认证模板解析---本地用户
  27. web api 单点登录(SSO) 权限验证
  28. 使用 DotNetOpenAuth 搭建 OAuth2.0 授权框架
  29. 用于新浪微博,腾讯QQ,淘宝 OAuth2.0 登陆的 NET 类库封装

并非都是赞美

  1. OAuth 2.0 - 通往地狱之路 (posted on 2012-08-05)
  2. OAuth 的权限问题与信息隐忧

淘宝 API

  1. 淘宝 API 采用 REST 风格

深入理解 OAuth2.0 协议 - 节选

Source: 帮你深入理解 OAuth 2.0 协议 - Tony praise

协议的参与者

OAuth 的参与实体至少有如下三个:

  • RO (resource owner): 资源所有者,对资源具有授权能力的用户。
  • RS (resource server): 资源服务器,它存储资源,并处理对资源的访问请求。如 Google 资源服务器,它所保管的资源就是用户的照片等。
  • Client: 第三方应用,它获得 RO 的授权后便可以去访问 RO 的资源。如网易印像服务。

此外,为了支持开放授权功能以及更好地描述开放授权协议,OAuth 引入了第四个参与实体:

  • AS (authorization server): 授权服务器,它认证 RO 的身份,为 RO 提供授权审批流程,并最终颁发授权令牌 (Access Token)。请注意,为了便于协议的描述,这里只是在逻辑上把 AS 与 RS 区分开来;在物理上,AS 与 RS 的功能可以由同一个服务器来提供服务。

授权类型

在开放授权中,第三方应用 (Client) 可能是一个 Web 站点,也可能是在浏览器中运行的一段 JavaScript 代码,还可能是安装在本地的一个应用程序。这些第三方应用都有各自的安全特性。对于 Web 站点来说,它与 RO 浏览器是分离的,它可以自己保存协议中的敏感数据,这些密钥可以不暴露给 RO;对于 JavaScript 代码和本地安全的应用程序来说,它本来就运行在 RO 的浏览器中,RO 是可以访问到 Client 在协议中的敏感数据。

OAuth 为了支持这些不同类型的第三方应用,提出了多种授权类型,如:

  • 授权码 (Authorization Code Grant)
  • 隐式授权 (Implicit Grant)
  • RO 凭证授权 (Resource Owner Password Credentials Grant)
  • Client 凭证授权 (Client Credentials Grant)

其中最核心、最难理解、也是最广泛使用的一种授权类型为 "授权码"。

授权码类型的开放授权协议的流程

  1. Client 初始化协议的执行流程。首先通过 HTTP 302 来重定向 RO 用户代理到 AS。Client 在 redirect_uri 中应包含如下参数:client_id,scope (描述被访问的资源),redirect_uri (即 Client 的 URI),state (用于抵制 CSRF 攻击)。此外,请求中还可以包含 access_type 和 approval_prompt 参数。当 approval_prompt=force 时,AS 将提供交互页面,要求 RO 必须显式地批准 (或拒绝) Client 的此次请求。如果没有 approval_prompt 参数,则默认为 RO 批准此次请求。当 access_type=offline 时,AS 将在颁发 access_token 时,同时还会颁发一个 refresh_token。因为 access_token 的有效期较短 (如 3600 秒),为了优化协议执行流程,offline 方式将允许 Client 直接持 refresh_token 来换取一个新的 access_token。
  2. AS 认证 RO 身份,并提供页面供 RO 决定是否批准或拒绝 Client 的此次请求 (当 approval_prompt=force 时)。
  3. 若请求被批准,AS 使用步骤 1 中 Client 提供的 redirect_uri 重定向 RO 用户代理到 Client。redirect_uri 须包含 authorization_code,以及步骤 1 中 Client 提供的 state。若请求被拒绝,AS 将通过 redirect_uri 返回相应的错误信息。
  4. Client 拿 authorization_code 去访问 AS 以交换所需的 access_token。Client 请求信息中应包含用于认证 Client 身份所需的认证数据,以及上一步请求 authorization_code 时所用的 redirect_uri。
  5. AS 在收到 authorization_code 时需要验证 Client 的身份,并验证收到的 redirect_uri 与第 3 步请求 authorization_code 时所使用的 redirect_uri 相匹配。如果验证通过,AS 将返回 access_token,以及 refresh_token (若 access_type=offline)。

步骤 4 中,Client 需要拿 "授权码" 去换 "授权令牌" 时,Client 需要向 AS 证明自己的身份,即证明自己就是步骤 2 中 Alice 批准授权时的 Grantee。这个身份证明的方法主要有两种:

  1. 通过 https 直接将 client_secret 发送给 AS,因为 client_secret 是由 Client 与 AS 所共享,所以只要传送 client_secret 的信道安全即可。
  2. 通过消息认证码来认证 Client 身份,典型的算法有 HMAC-SHA1。在这种方式下,Client 无需传送 client_secret,只需发送消息请求的 signature 即可。由于不需要向 AS 传递敏感数据,所以它只需要使用 http 即可。

此外,在步骤 2 中,Google 授权服务器需要认证 Alice 的 RO 身份,并提供授权界面给 Alice 进行授权审批。

为何引入 authorization_code

协议设计中,为什么要使用 authorization_code 来交换 access_token?这是读者容易想到的一个问题。也就是说,在协议的第 3 步,为什么不直接将 access_token 通过重定向方式返回给 Client 呢?如果直接返回 access_token,协议将变得更加简洁,而且少一次 Client 与 AS 之间的交互,性能也更优。那为何不这么设计呢?协议文档中并没有给出这样设计的理由,但也不难分析:

  1. 浏览器的 redirect_uri 是一个不安全信道,此方式不适合于传递敏感数据 (如 access_token)。因为 uri 可能通过 HTTP referrer 被传递给其它恶意站点,也可能存在于浏览器 cacher 或 log 文件中,这就给攻击者盗取 access_token 带来了很多机会。另外,此协议也不应该假设 RO 用户代理的行为是可信赖的,因为 RO 的浏览器可能早已被攻击者植入了跨站脚本用来监听 access_token。因此,access_token 通过 RO 的用户代理传递给 Client,会显著扩大 access_token 被泄露的风险。但 authorization_code 可以通过 redirect_uri 方式来传递,是因为 authorization_code 并不像 access_token 一样敏感。即使 authorization_code 被泄露,攻击者也无法直接拿到 access_token,因为拿 authorization_code 去交换 access_token 是需要验证 Client 的真实身份。也就是说,除了 Client 之外,其他人拿 authorization_code 是没有用的。此外,access_token 应该只颁发给 Client 使用,其他任何主体 (包括 RO) 都不应该获取 access_token。协议的设计应能保证 Client 是唯一有能力获取 access_token 的主体。引入 authorization_code 之后,便可以保证 Client 是 access_token 的唯一持有人。当然,Client 也是唯一的有义务需要保护 access_token 不被泄露。
  2. 引入 authorization_code 还会带来如下的好处。由于协议需要验证 Client 的身份,如果不引入 authorization_code,这个 Client 的身份认证只能通过第 1 步的 redirect_uri 来传递。同样由于 redirect_uri 是一个不安全信道,这就额外要求 Client 必须使用数字签名技术来进行身份认证,而不能用简单的密码或口令认证方式。引入 authorization_code 之后,AS 可以直接对 Client 进行身份认证 (见步骤 4 和 5),而且可以支持任意的 Client 认证方式 (比如,简单地直接将 Client 端密钥发送给 AS)。

在我们理解了上述安全性考虑之后,读者也许会有豁然开朗的感觉,懂得了引入 authorization_code 的妙处。那么,是不是一定要引入 authorization_code 才能解决这些安全问题呢?当然不是。笔者将会在另一篇博文给出一个直接返回 access_token 的扩展授权类型解决方案,它在满足相同安全性的条件下,使协议更简洁,交互次数更少。

基于 Web 安全的考虑

OAuth 协议设计不同于简单的网络安全协议的设计,因为 OAuth 需要考虑各种 Web 攻击,比如 CSRF (Cross-Site Request Forgery)、XSS (Cross Site Script)、Clickjacking。要理解这些攻击原理,读者需要对浏览器安全 (eg, Same Origin Policy, 同源策略) 有基本理解。比如,在 redirect_uri 中引入 state 参数就是从浏览器安全角度考虑的,有了它就可以抵制 CSRF 攻击。如果没有这个参数,攻击者便可以在 redirect_uri 中注入攻击者提供的 authorization_code 或 access_token,结果可能导致 Client 访问错误的资源 (比如,将款项汇到一个错误的帐号)。

JWT (JSON Web Token)

JWT 是一种安全标准。基本思路就是用户提供用户名和密码给认证服务器,服务器验证用户提交信息信息的合法性; 如果验证成功,会产生并返回一个 Token (令牌),用户可以使用这个 token 访问服务器上受保护的资源。

IdentityServer

http://github.com/IdentityServer/IdentityServer4 - OpenID Connect and OAuth 2.0 Framework for ASP.NET Core
http://identityserver.io