My understanding of OAuth 1.0

引子

网上现在介绍OAuth时,大多是把OAuth core中的3 steps和一张summary图copy过来完事。

OAuth Authentication is done in three steps:

  1. The Consume r obtains an unauthorized Request Token.
  2. The User authorizes the Request Token.
  3. The Consumer exchanges the Request Token for an Access Token.

有图有真相:http://oauth.net/core/diagram.png

 

好吧,

如果你能拿起笔来顺手就画出3steps,理解就基本ok。

如果你可以自己写个oauth client,整个spec的细节都已掌握。

如果你可以自己实现oauth server,则算是融汇贯通了。

如果你知道oauth的安全漏洞和微弱环节,那么你肯定是安全专家。

 

本篇文章的目标是第一个,帮你理解oauth。

My understanding of OAuth

what's the problem it solve?

3 legs problem. 随着web2.0的兴起,大量的网站都提供了API来暴露用户的数据给第三方应用。web2.0是啥,就是UGC(user generated content),从blog, photo到现在的sns,微博。大量的用户产生了大量的数据,这些网站渐渐演变成一个平台。第三方可以接入平台,开发自己的应用。而接入,就是调用平台提供的API得到用户的数据,衍生自己的应用。

 

用例一:用户使用每个网站和应用时,首先需要注册,填入ID,登录密码,邮箱,姓名等等个人资料。如果是在某开放平台上开发,则可省去这一环,用户登录平台后可授权应用开发商,将自己的个人资料从平台中导入。(openid + oauth 提供了完整的用户免注册问题)

 

用例二:照片打印服务(官网中的例子)。有用户在Flick或者Picassa上传了一次在三藩旅游的照片,然后他想通过另外一个照片打印服务商(比较便宜)将这次旅游的照片打印成册。

 

Basic auth时代,用户直接将自己的username和password告诉给第三方应用。比如名单导入和好友邀请,网站会提示:请输入msn用户和密码,本网站将保证不会泄漏.....

 

直接交出用户名和密码无疑是很危险的事

  • No control of the access. "本网站保证不会泄漏....",不代表该网站不会在取得你的联系人名单时,顺带定期读取你的email,分析email内容,给你投放定向广告。打印服务商可能不光是将三藩旅游的照片打印出来,可能你XXOO的也一并捎带。

不交出用户名和密码,如何授权给应用?

  • oauth is try to solve the delegation (authorization) problem in a secure way in non https-environments 

Some knowledge about security 

oauth问题很简单,然而过程却有点trouble。要理解这些过程,首先补充下关于计算机网络安全的知识。

数字签名

在现实生活中,我们使用银行卡时,需要卡号(ID)和密码;网站登录需要ID(user)和Password。ID是用户唯一标认,而password则是用户身份验证(authentication)

 

数字签名的作用一样:A valid digital signature gives a recipient reason to believe that the message was created by a known sender, and that it was not altered in transit. 

一是验证文档用户(authentication)的身份,二是保证其没被更改(integration) -- 好比我们手填一些单子时,不容许有涂改。

 

怎样做呢?把用户的ID和password连同文档一块发出去? 搞计算机密码学的不同意! 

  • unencrypted password is not allowed in computer cryptology

我们使用信用卡时,无需透露信用卡给商家,只需一个签名即可。密码学的同仁采取了类似的做法:

  1. 使用hash fucntion生成文档(数据)的一个hash值。具体的hash函数不作深究,比如:取模hash,可以将所有data的byte直接相加,然后取个模。
  2. 用一个private key将hash值加密形成数字签名。具体的加密算法不作深究,比如:将hash值和private key进行异或操作。
  3. 把用户的Certificate (treat as a ID)和数字签名(treat as password)连同文档一块发出。

服务器端

  1. 根据文档的Certificate找到用户对应的public key。
  2.  使用public key来解密hash value, 得到原始hash值。对应上文:将hash值和public key进行异或操作(假定是shared secret key, 公钥和私钥相同)
  3. 使用相同的hash function计算生成文档的hash值。对应上文:取模hash
  4. 将两个hash值比较。如果不同,则说明文档或者被篡改(data is changed),或者用户身份不对(public key is not right, so certificate is not right)

 

 

 

http://en.wikipedia.org/wiki/File:Digital_Signature_diagram.svg

hash function

 MD5 (Message-Digest algorithm 5):生成 128-bit (16-byte) hash value. 32个16进制数(4 bit一个hexadecimal number.)

 

 SHA1 (Secure Hash Algorithm): 生成160-bit hash value.

signature method(加密方法)

HMAC(Hash-based Message Authentication Code)

HMAC-SHA1

 

RSA(RivestShamir and Adleman ) is an algorithm for public-key cryptography 

RAS-SHA1

Some knowledge about sniffing the network

重放攻击:将合法的请求重新发给服务器,从而获取用户数据。

 

防止重放攻击:在request中加入nonce(number used once),一个随机的unique string。服务器端在响应一次请求后,如果第二次接到相同的相应,可认为这是个重放攻击,直接reject。

 

timstamp: server端要实现重放攻击,必须记录所有曾经的nonce值,超超大的数据库才行。为了降低server端维护nonce的成本,request加入时间戳。server端只记录一段时间内的nonce值(比如一个小时内),如果timestamp older 1小时,server端可直接reject。因为没有保存更老的nonce值,无法验证其unique。

The concept(Terminology) of oauth

client:  An HTTP client, 第三方应用(曾经叫consumer)

server:  An HTTP client,拥有资源或者响应授权请求(authenticated requests)的平台

protected resource:用户数据

resource owner:用户

credentials(证书):可理解为ID和Password。如同前文介绍,oauth使用数字签名的一套,所以不完全等同。

  • client credentials: consumer key/secret (nearly same with ID/password)
  • temporary credentials: the authorization request (request token/secret)
  • token: access grant (access token/secret)

token:上面credentials中的token,表示用户对某个应用的授权。唯一标示符和一个相应的shared-secret来签名加密(验证身份)

理论上只要两种credentials即可,一个是client应用本身的key/secret来标识应用;另外一个是表示用户对应用的授权,用户同意第三方应用访问用户的数据后,由server端生成一组access token/secret。第三方应用使用该授权(唯一标识符+secret)请求用户的数据。oauth的目标在此体现:

The decoupling of the User’s username and password from the Token is one of the most fundamental aspects of the OAuth architecture.

token/secret 和 username/password的区别在哪?理论上我们也可以使用password来进行数字签名,避免密码的明文传输。使用token的好处是可以随时revoke,可以有不同的access control。比如同一个用户授权A访问folder1,授权B访问folder2,生成不同的token,互不影响。比如限制一个token的有效期为1小时,平台不可能要求用户每一小时更换一个密码。

 

顺延这个思路,consumer key/consumer sercet作为应用的唯一标识,欠缺一定的灵活性。引入request token/secret,增加更多的控制。比如同样可以为request token设置有效期,如果应用在1小时内仍没有使用该token取得任何用户的授权,则该request token 过期。在oauth2中request token变为refresh token,由server端在返回access token时一块返回,简化了流程。

The process of oauth

From the user point (user channel)

从用户的角度看,过程如下:

  • 访问某个应用
  • 被重定向到平台,提示yes or no授权给应用。
  • 点击yes(如果没有登录平台,则需输入用户名和密码),被重定向回应用页面
  • 应用页面显示用户的数据
Backgroud channel

step1, 在用户访问应用页面时,client get request token from server。Authorization header的内容如下,不考虑验证部分,consumer_keycallback为输入,request_token/secret为输出

Request  

     POST /request_temp_credentials HTTP/1.1
     Host: server.example.com
     Authorization: OAuth realm="Example",
        oauth_consumer_key="jd83jd92dhsh93js",
        oauth_signature_method="PLAINTEXT",
        oauth_callback="http%3A%2F%2Fclient.example.net%2Fcb%3Fx%3D1",
        oauth_signature="ja893SD9%26"

Response  

     HTTP/1.1 200 OK
     Content-Type: application/x-www-form-urlencoded

     oauth_token=hdk48Djdsa&oauth_token_secret=xyz4992k83j47x0b&
     oauth_callback_confirmed=true

 

 

step2, 用户被重定向到平台授权页面。请求输入为第一步中返回的request_token, 输出为verifier(request_toekn原样返回)

Request (重定向到平台)

     GET /authorize_access?oauth_token=hdk48Djdsa HTTP/1.1
     Host: server.example.com
Response(重定向返回应用)
    GET /cb?x=1&oauth_token=hdk48Djdsa&oauth_verifier=473f82d3 HTTP/1.1
    Host: client.example.net

 

 

setp3, client使用consumer_key, request_token, verifier来换取access_token

Request

   POST /request_token HTTP/1.1
     Host: server.example.com
     Authorization: OAuth realm="Example",
        oauth_consumer_key="jd83jd92dhsh93js",
        oauth_token="hdk48Djdsa",
        oauth_signature_method="PLAINTEXT",
        oauth_verifier="473f82d3",
        oauth_signature="ja893SD9%26xyz4992k83j47x0

Response

     HTTP/1.1 200 OK
     Content-Type: application/x-www-form-urlencoded

     oauth_token=j49ddk933skd9dks&oauth_token_secret=ll399dj47dskfjd

 

接下应用使用consumer_key, access_token来取得用户数据,这时需要加入noncetimestamp防止重放攻击。
   POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
     Host: example.com
     Content-Type: application/x-www-form-urlencoded
     Authorization: OAuth realm="Example",
                    oauth_consumer_key="9djdj82h48djs9d2",
                    oauth_token="kkk9d7dh3k39sjv7",
                    oauth_signature_method="HMAC-SHA1",
                    oauth_timestamp="137131201",
                    oauth_nonce="7d8f3e4a",
                    oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"

     c2&a3=2+q

The sign of oauth

上面3步,其签名过程都一致(所有的Authorization header中都加入了signature_method和signature), 数字签名用的key是(HMAC-SHA1:consumer_secret&token_secret).

签名的内容(base string)如下。spec中详细定义了签名的base string内容和编码,

其中parameter部分包括所有The OAuth HTTP "Authorization" header field(除了oauth_signature)

1.  The HTTP request method in uppercase.  For example: "HEAD",
       "GET", "POST", etc.  If the request uses a custom HTTP method, it
       MUST be encoded (Section 3.6).

   2.  An "&" character (ASCII code 38).

   3.  The base string URI from Section 3.4.1.2, after being encoded
       (Section 3.6).

   4.  An "&" character (ASCII code 38).

   5.  The request parameters as normalized in Section 3.4.1.3.2, after
       being encoded (Section 3.6).

Future topic

上述过程只讨论了client端的流程,server端的实现可参见:

Client/Server code

https://github.com/leah/python-oauth/

https://github.com/brosner/python-oauth2

DB Design

http://stackoverflow.com/questions/4534337/what-is-the-recommended-database-structure-for-oauth-provider

http://oauth.riaforge.org/

Reference

beginners guide: beginners-guide-to-oauth-part-iii-security-architecture

guide: http://hueniverse.com/oauth/guide/intro/

oauth1.0 spec: rfc5849 spec

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FireCoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值