Auth介绍 - 协议解析
OAuth
是一个开放的授权协议,它提供一个方法可以让你授权某个人(记为Client)来代表你(记为Resource Owner 或 Web
User)去访问你保存在服务器(记为Server)上的资源。rfc5849是描述OAuth1.0的标准文档,可作为开发OAuth协议的参考。
我之前的Blog (OAuth介绍 - 使用场景)描述了OAuth的一个经典用例。本文将对OAuth协议进一步阐述,使OAuth开发者能更容易理解OAuth的工作原理。
一、OAuth协议的初始化
OAuth
的参与者有Server、Client和Resource
Owner(说明:为了与rfc5849保持一致,我对协议参与者的称谓做了修改:Client对应前Blog的Consumer,Resource
Owner对应为User,而Server则对应为Service
Provider。)为便于理解,读者可以把Server看作是提供照片存储服务的网站photos.example.net,把Client看作是提供
打印服务的网站printer.example.com,而Resource Owner则看作一个web用户。
协议运行之前,Server要初始化并公开如下三个URI:
(1) Temporary Credential Request URI: https://photos.example.net/initiate
(2) Resource Owner Authorization URI: https://photos.example.net/authorize
(3) Token Request URI: https://photos.example.net/token
并
且,Client需要向Server进行注册以获得用户认证所需的client
credentials(客户端凭据),也就是一个二元组(oauth_consumer_key,
oauth_consumer_secret)。我们例子中的client credentials为如下的值:Client Identifier
(oauth_consumer_key) = dpf43f3p2l4k3l03,Client Shared-Secret
(oauth_consumer_secret) = kd94hf93k423kf44。
二、OAuth协议描述
OAuth
协议由Web User (Resource
Owner)来触发,通过三方的多次交互,最终使Client获得能访问Server上特定资源的一个Token。协议能保证不会泄露User的认证凭据
(比如登录Server的用户名和密码)给Client。协议中三方的一系列交互从功能上来讲实际是在完成以下三件事情,下面分别悉数之。
1. Temporary Credential Request
如图1所示,该过程仅仅涉及到Client和Server之间的交互,目的是让Client获取一个临时凭证(Temporary Credential)用于后续交互过程的消息认证,这个临时凭证仅在OAuth session中有效,协议结束后消亡。
step 1:
在https request中,Client必须提供oauth_callback,否则在resource owner授权完成之后(step
6),Server无法通过“重定向”方法将控制权交给Client。而oauth_consumer_key,
oauth_signature_method和oauth_signature则是用于消息认证(包括消息源认证和消息完整性认证)。用于消息认证的方
法两类:基于共享密钥的HMAC和基于非对称密钥的数字签名。OAuth 1.0将消息认证方法统一记为signature
(数字签名),并明确支持HMAC-SHA1,
RSA-SHA1和PLAINTEXT(不计算消息认证码,而是直接将密钥通过安全信道发送),当然Client也可以选择自己的消息认证方法。
step 2: 在http response中,Server将返回给Client一个临时凭证,即二元组(oauth_token, oauth_token_secret),以及对后续步骤6的callback行为的确认。
2. Resource Owner Authorization
现
在Client重定向User的浏览器到Server的授权页面。授权过程需要:(1)认证User的resource
owner身份;(2)提供足够的信息使User能作出授权决定;(3)将User的授权决定告知Client。这一过程对应协议中的第3~6步,如图2
所示。
图2. Resource Owner Authorization
step 3: Client重定向User浏览器到Server公开的Authorization URI。此时Server要求User提供认证凭据(如username + password)以证明其resource owner的身份。
step 4: 当User的身份得到验证后,Server将待授权信息告知User。需要告知的信息至少应包含授权必须的三项基本要素:(Principal, Action, Resource),但可能还包含某些限制条件,如ExpiredTime。
step 5: User根据以上信息作出授权决定:Allow或Deny。
step 6: Server重定向User的浏览器到Client在step1中提供的callback地址,通知Client关于User的授权决定。如果User的决定是Deny,协议将终止;如果是Allow,则继续。
在
所有的交互过程中,临时凭证ID(即oauth_token)总是被携带着用于标识此次授权session。但值得注意到的是:在step
6的callback地址还包含了一个oauth_verifier参数,它实际上就是Server端产生的一个nonce(只使用一次的数),它的作用
是确保调用callback地址的User就是前面步骤中做出授权决定的Resource Owner。
3. Token Request
当Client知道User的授权已经完成之后,它将开始请求能真正访问资源的token了。请求token的过程如图3所示。
图3. Token Request
step 7: 在https请求中,oauth_token是step 2获得的临时凭证ID,它的生命周期即将结束。oauth_verifier是step 6中Server通过User浏览器重定向方法传过来的nonce。其它的参数则用于消息认证。
step 8: 在Response中,Client将收到真正用于访问User资源的token,它和临时凭证的形式完全一样,也是二元组(oauth_token, oauth_token_secret)。至此,临时凭证也就不再需要了。
注
意,Client最终获得的token的作用仅仅是用于消息认证。token就是一个索引,它背后所代表的意义 —— Resource
Owner授权Client去访问Server上的某个资源,则完全由Server来理解。因此,Server必须是有状态的,它要保存token所代表
的访问控制信息。
三、请求资源访问
一旦Client获得了有效的token,它便可以访问User保存在Server上的资源了。请求资源访问方法如图4所示。
图4. Resource Access Request
在 https的访问请求中,oauth_nonce则是为了抗重放攻击(anti-replay),参数oauth_consumer_key和 oauth_token共同参与消息认证。这两个凭证是如何共同参与消息认证呢?这个很简单,比如采用HMAC-SHA1签名方法,签名密钥= > & <oauth_token_secret>,它是由client shared-secret与token shared-secret串接而成。而签名基串(signature base string)的构造方法在rfc5849中有非常详细的描述,读者有兴趣可以参考rfc5849。
四、应用现状
随着Internet客户端工具的日益丰富和多样化,特别是移动互联网的兴起,OAuth的应用越来越广泛。目前已经存在很多开源的实现,如使用较广泛的有code repository on Google Code. 另外,Google OAuth 还提供了一个Demo环境(http://googlecodesamples.com/oauth_playground/),有兴趣的同学可以去体验一下。
设 计OAuth的最初动机主要是针对浏览器应用,并没有过多考虑客户端的多样化。那么对于某些特定的应用场合来说,OAuth协议显得过于复杂,而且频繁的 交互操作可能会导致不可接受的性能开销。历史告诉我们:任何过于复杂的安全协议最终都会被用户所抛弃。那么如何使OAuth变得更简单易用?人们正在探 索,OAuth2.0就是这条探索之路上的一个方向。关于OAuth2.0,且听下回分解。
五、参考文献
[RFC5849] The OAuth 1.0 Protocol.
[RFC2616] Hypertext Transfer Protocol -- HTTP/1.1
[RFC2818] HTTP Over TLS