这两天工做中又用到了Auth2.0协议,发现以前看的已经忘了差很少了。因此想写篇BLOG记下,加深下印象
根据RFC6749协议介绍,Auth2.0是一个受权(官方用的是authorization,这里要注意受权authorization和认证authentication的区别)协议,它容许第三方应用经过Http Service来获取部分权限。api
RFC6749协议给出的受权流程图以下:浏览器
+--------+ +---------------+ | |--(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 ---| | +--------+ +---------------+ Figure 1: Abstract Protocol Flow
A. 第三方应用发起受权
B. 平台方弹出受权页面,页面显示受权范围
C. 用户赞成受权,而后第三方应用去获取access_token
D. 平台方返回access_token
E. 而后第三方应用拿获取到的access_token去调用平台方api
F. 平台方返回资源app
auth2.0有4中受权方式
Authorization Code方式是用的最多的一种方式,流程以下:编码
+----------+ | Resource | | Owner | | | +----------+ ^ | (B) +----|-----+ Client Identifier +---------------+ | -+----(A)-- & Redirection URI ---->| | | User- | | Authorization | | Agent -+----(B)-- User authenticates --->| Server | | | | | | -+----(C)-- Authorization Code ---<| | +-|----|---+ +---------------+ | | ^ v (A) (C) | | | | | | ^ v | | +---------+ | | | |>---(D)-- Authorization Code ---------' | | Client | & Redirection URI | | | | | |<---(E)----- Access Token -------------------' +---------+ (w/ Optional Refresh Token)
A. 第三方应用发起受权
B. 用户赞成受权
C. 平台方重定向到事先约定好的URL,并在URL里附加上code参数
D. 第三方应用解析URL并作参数校验后,用code和在平台方生成的key和secret去换access_token
E. 平台方作校验后放回access_token
F. 第三方应用用拿到的access_token去获取用户受权的数据url
与简化模式(Implicit)不一样的是,Authorization Code获取access_token是在第三方应用的Server上进行的,所以access_token并不会暴露给浏览器或者客户端code
简化模式(Implicit)是受权码模式(Authorization Code)的简化版,是给用浏览器做为客户端的应用用的,流程图以下orm
+----------+ | Resource | | Owner | | | +----------+ ^ | (B) +----|-----+ Client Identifier +---------------+ | -+----(A)-- & Redirection URI --->| | | User- | | Authorization | | Agent -|----(B)-- User authenticates -->| Server | | | | | | |<---(C)--- Redirection URI ----<| | | | with Access Token +---------------+ | | in Fragment | | +---------------+ | |----(D)--- Redirection URI ---->| Web-Hosted | | | without Fragment | Client | | | | Resource | | (F) |<---(E)------- Script ---------<| | | | +---------------+ +-|--------+ | | (A) (G) Access Token | | ^ v +---------+ | | | Client | | | +---------+
密码模式是将用户在平台上的帐户密码提供给第三方应用,好比各类抢火车票的软件用的这种模式。这种认证模式的缺点显而易见。csrf
客户端模式指客户端以本身的名义,向"服务提供商"进行认证blog
Authorization Request的参数是以 application/x-www-form-urlencoded方式写到URL上的
response_type: 值必须设置为code,token或者其余约定的值
client_id: 平台方分给应用方的Id
redirect_uri(可选): 回调url,redirect_uri必须作严格限制,以Github为例token
CALLBACK: http://example.com/path
GOOD: http://example.com/path
GOOD: http://example.com/path/subdi...
BAD: http://example.com/bar
BAD: http://example.com/
BAD: http://example.com:8080/path
BAD: http://oauth.example.com:8080/path
BAD: http://example.org
scope: 应用方申请的权限范围,这个是由平台方定义的
state: state的值建议设置为不可猜想的,其目的是防止csrf攻击
code: 平台方传给应用方的code,应用方的在请求access_token的是有用到。code只能用一次。并且当code被使用屡次的时候,平台方应当拒绝请求,而且回收全部已经分配的access_token(文档建议这么作,但实际上没见到有平台作这么严格)
做为平台方,code应当和client_id是对应的,是为了防止攻击者截取回调请求,并将code替换为事先准备好的code,从而诱导用户绑定攻击者本身的应用,从而窃取用户信息
state: 应用方传给平台方的state参数,平台方回回传给应用方。state是用来防止csrf攻击的,所以它的值是应该通过编码的,
refresh_token: refresh_token是可选的,当access_token过时时,能够用refresh_token去获取新的access_token
官方文档,注意文档中MUST
和SHOULD
,NOTE
等字眼,这里面写着最佳实践和一些所谓的坑
知道创宇的一篇关于OAuth漏洞的分析与防范建议