对oauth2.0的一知半解

有一天

  1. 你有很多钻石,托管在银行仓库的保险箱里。
  2. 你想请人帮你鉴定这些钻石的纯度,又不想总是跑去银行,就让鉴定师自己去银行好了。
  3. 鉴定师跟银行说要拿出你的宝石来给他鉴定。
  4. 银行不相信,怎么办?
  5. 打电话给你,你确认授权哪个保险箱给鉴定师
    • 授权哪种权限 grant type
  6. 银行给了你临时凭证code,你把code给鉴定师(302重定向)
  7. 鉴定师拿着这个code去银行换临时钥匙accessToken
  8. 银行验证code ok,发给鉴定师一把仓库某保险箱的临时钥匙accessToken,还有这个钥匙对应哪个用户的openid
  9. 鉴定师凭着这把临时钥匙就可以开你的保险箱拿到你的宝石验证了。
  10. 如果临时钥匙过期,就得再申请一把(freshToken)image
  • 以上这种授权类型是Authorization Code(response_type=code)。

  • 还有另外一种简化版的认证类型Implicit(response_type=token)
    • Implicit则是不发code,银行直接发给鉴定师一把仓库某保险箱的临时钥匙accessToken,其它流程差不多。image

角色定义

这里出现了四个角色。

  1. 你相当于 Resource Owner
  2. 鉴定师相当于Client
  3. 银行相当于Authorization Server
  4. 仓库相当于Resource Server

说白了

An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.
OAuth is a simple way to publish and interact with protected data. It’s also a safer and more secure way for people to give you access. We’ve kept it simple to save you time.

OAuth就是第三方的应用可以通过你的授权而不用知道你的帐号密码能够访问你在某网站的你自己的数据或功能。
当OAuth提供方询问用户并得到授权,就会给予第三方服务一些权限做相对应的操作。

谁都不相信谁

由于这三个角色都不相信对方,那么就需要这写参数来证明身份不是假冒的了。

  • 你 Resource Owner
  • 鉴定师 Client
  • 银行相 Authorization Server

appid

鉴定师在银行注册,银行给每个鉴定师编号appid,从而可以辨识多个鉴定师。

secret

  • 鉴定师在银行注册时,双方约定好一个秘密信物secret。
  • 日后鉴定师凭code来获取accessToken时,需要带上secret来向银行证明自己不是假冒的。
  • 也避免了DNS 污染。

state

  • 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验,即用即毁。
  • 攻击者调换了自己的code给你,你把攻击者的临时凭证给了鉴定师,鉴定师便以为拿到了你的临时钥匙,实际上拿的是攻击者的临时钥匙。如果你让鉴定师帮忙再放个宝石进保险箱里,实际上是放进了攻击者的保险箱里。
  • 因此,鉴定师要用state来检验你就是你,而不是攻击者。也即鉴定师让你打电话给银行的那个你,和把code给鉴定师的的那个你,是同一个。

code

  • 这个code很有可能被攻击者截取了,可能发生在银行告诉你的过程中,也可能发生在你告诉鉴定师的过程中。
  • 所以这两个过程最好使用https协议,尽量不要连不安全的wifi。
  • 由于code只能用一次,而且一般10分钟后过期。
  • 如果有另外一个鉴定师也拿着这个code来获取accessToken,那么银行设置之前通过此code 获取的 access token失效。
  • 所以即使code被截取了也不会为时过晚,鉴定师紧跟攻击者后把code给银行,银行发现不对劲,立即撤销accessToken。
  • 攻击者还没用accessToken拿到宝石,这临时钥匙就失效了。。

redirect_uri

相当于鉴定师在银行注册时的手机号。

  • (微信网页授权的情形下,是鉴定师把自己的手机号和state告诉给你,让你打电话给银行确认授权)
  • 你跟银行确认授权(已经登陆了就用cookie)哪个保险箱给鉴定师时,顺便把state、权限范围scope、鉴定师appid、鉴定师的号码也给了银行。
  • 银行确认了你授权,把你给的手机号和鉴定师在银行注册时的手机号进行校验。
  • 检验无误后,把code给你,手机号也给回你。
  • 你自动根据这个电话给鉴定师,告诉他这个code。
  • 如果银行不校验这个手机号,就很有可能误导你打错电话,把code告诉给了别人。
  • 又或者银行完整校验这个手机号,这个手机号可能转播给攻击者。

accessToken

临时调用接口凭证,2小时

granttype

说明是哪种授权方式,authorization_code还是implict。
和code一起给银行

scope

授予哪种权限范围,微信有两种snsapi_base、snsapi_userinfo

openid

鉴定师的客户在银行里的唯一标识

unionid

鉴定师联盟的客户在银行里的唯一标识

防范

  1. 你得找个可靠的鉴定师,只授权给可信的第三方应用
  2. 银行要验证鉴定师是否假冒的,对redirect_uri进行全路径验证,避免绕过

oauth2改进了oauth1哪些不足?

  • OAuth分为OAuth以及OAuth 2.0。
  • OAuth Core 1.0 版本发布于2007年12月4日,存在可被会话定向攻击(session fixation)
  • OAuth 2.0 一定程度上防范中间人攻击。

总结

  1. 银行通过secret信任鉴定师,鉴定师通过state信任你。
  2. 至于银行和仓库之间如何规定好accessToken则是后话了
  3. 还有其它的安全问题可参考rfc的第十章

参考

  1. rfc6749/rfc6749
  2. OAuth 2.0 筆記 (1) 世界觀
  3. 理解OAuth 2.0
  4. oauth_vulnerability_analysis
  5. security-issue-about-oauth-2-0-you-should-know
  6. wx文档1
  7. wx文档2
`