OAuth 协议详解

OAuth 简介

官网上的介绍:

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

OAuth 的安全性

OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准,OAuth 的授权使第三方不触及到用户的帐号信息(如用户名与密码),即可申请获得该用户资源的授权。而且所有 HTTP 请求都采用非对称加密算法对请求进行了加密。

OAuth 的开放性

任何第三方都可以使用 OAuth 认证服务,任何服务提供商都可以实现自身的 OAuth 认证服务。

OAuth 的历史

关于OAuth前世今生的一些八卦,还是挺有意思的。

挑点有意义的时间节点:

  1. 2006年12月,twitter 的首席架构师 Blaine Cook 召集了一拨人开始搞 OAuth 协议;
  2. 2007年12月,OAuth Core 1.0 协议说明文档定稿;
  3. 2009年4月,twitter 基于 OAuth1.0 推出“使用 twitter 登录”;
  4. 2010年6月,OAuth 1.0a 作为rfc5849发布;
  5. 2012年10月,OAuth 2.0 作为rfc6749发布;

OAuth 1.0a 的流程详解

示例源自rfc.

这个例子的图文流程.

这个例子的协议详解.

约定前提

  • 第三方:printer.example.com
  • 服务方:photos.example.net
  • 第三方注册在服务方的id:dpf43f3p2l4k3l03, 约定共享密钥: kd94hf93k423kf4

step 1. 请求临时token

POST /initiate HTTP/1.1
Host: photos.example.net
Authorization: OAuth realm="Photos",
   oauth_consumer_key="dpf43f3p2l4k3l03", // 注册的第三方服务id
   oauth_signature_method="HMAC-SHA1", // 签名方法
   oauth_timestamp="137131200", // 时间戳
   oauth_nonce="wIjqoS", // 随机的混淆字符串
   oauth_callback="http%3A%2F%2Fprinter.example.com%2Fready", // 经过编码的回调url
   oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D" // 签名

step 2. 获得临时token

HTTP/1.1 200 OK
Content-Type: application/x-www-form-urlencoded
oauth_token=hh5s93j4hdidpola&  // 临时token
oauth_token_secret=hdhd0244k9j7ao03& // 临时token密钥
    oauth_callback_confirmed=true // 确认回调url

step 3.第三方引导用户访问服务方,并期待用户授权

https://photos.example.net/authorize?oauth_token=hh5s93j4hdidpola

step 4. 服务方返回临时Token及用户的授权码(依赖回调url)

http://printer.example.com/ready?oauth_token=hh5s93j4hdidpola& oauth_verifier=hfdp7dh39dks988

step 5. 第三方请求正式token

POST /token HTTP/1.1
Host: photos.example.net
Authorization: OAuth realm="Photos",
   oauth_consumer_key="dpf43f3p2l4k3l03", // 注册的第三方服务id
   oauth_token="hh5s93j4hdidpola", // 临时token
   oauth_signature_method="HMAC-SHA1", // 签名方法
   oauth_timestamp="137131201", // 时间戳
   oauth_nonce="walatlh", // 随机的混淆字符串
   oauth_verifier="hfdp7dh39dks9884", // 授权码
   oauth_signature="gKgrFCywp7rO0OXSjdot%2FIHF7IU%3D" // 签名

step 6. 获得正式token

HTTP/1.1 200 OK
Content-Type: application/x-www-form-urlencoded
oauth_token=nnch734d00sl2jdk // 正式token
oauth_token_secret=pfkkdhi9sl3r4s00 // 正式密钥

step 7. 第三方请求服务

GET /photos?file=vacation.jpg&size=original HTTP/1.1
Host: photos.example.net
Authorization: OAuth realm="Photos",
   oauth_consumer_key="dpf43f3p2l4k3l03", // 注册的第三方服务id
   oauth_token="nnch734d00sl2jdk", // 正式token
   oauth_signature_method="HMAC-SHA1", // 签名方法
   oauth_timestamp="137131202", // 时间戳
   oauth_nonce="chapoH", // 随机的混淆字符串
   oauth_signature="MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D"  // 签名

关于签名算法,做一点补充:

  1. 签名的源是除了签名之外的所有字段,oauth_timestamp 和 oauth_nonce 字段保证了签名的随机性。
  2. 编码方式统一(%编码),保证了签名的一致性。
  3. 常用的 HMAC-SHA1 算法,使用私钥来加密,私钥只有第三方和服务方有,所以保证了安全。

OAuth 1.0a 的缺点

  1. 流程复杂,加密算法复杂,门槛高,无法方便的满足各种客户端实现。
  2. 没有强制https,协议数据容易被监听。
  3. 敏感资源应该防止被代理服务器cache。
  4. 授权的过程,容易被钓鱼网站欺骗,需要加强教育。
  5. 协议过程需要用到明文密码。
  6. 容易被 CSRF 攻击,关于 CSRF 可以参考这里
  7. 第三方的密钥的安全存储。

OAuth 1.0a 的完善

早期的 OAuth1.0 是有严重漏洞的:

OAuth 1.0 中,回调 url 是在第三步带上去的,这就导致攻击者可以利用钓鱼网站让受害者授权,并将回调 url 设为自己的站点,等到用户授权之后,访问合法的回调 url 来拿到受害者的 token。

OAuth 1.0a 已经解决了这个问题:OAuth 1.0a 要求将回调 url 提前,第一步就必须提供,并约定如果不需要重定向,则值为 oob。

其他参考